Reklama

zonerbooks.cz | zoner.cz | czechia.com | regzone.cz | inshop.cz | inmail.cz | zonerpress.cz | zonerantivirus.com | zonerama.cz

interval.cz

Řízené vkládání zdrojových kódů

07. 03. 2003 | Ondřej Jureček | PHP | Komentáře: 0

Čím větší projekt, tím je implementace složitější. Je potřeba komunikovat s databázovým serverem, FTP, IMAP, zpracovávat XML a jiné vstupy. V tomto článku se budu zabývat otázkou, jak správně a přehledně řídit zařazování kódu v rozsáhlém PHP skriptu. Využiji přitom metodu objektového programování, kdy vývojář píše jednotlivé komponenty a udržuje si pořádek stylem "co objekt, to samostatný soubor".

Máme-li určen cíl, pojďme si hned ukázat techniku, jak řídit řazení PHP kódu v programu. Já osobně v PHP programuji objektově. Každý objekt píši do vlastního souboru, udržuji ho pak v určeném adresáři. Uvažujme o hlavním skriptu index.php. Chci-li vytvořit objekt A (instanci třídy A), musí interpret PHP znát jeho definici třídy. Pak bych mohl psát:

<?php
$A = new class_a();
?>

Definici třídy class_a() uloženou v souboru class_a.php, musím načíst jedním z příkazů:

<?php
include 'class_a.php';
require 'class_a.php';
include_once 'class_a.php';
require_once 'class_a.php';
?>

Rozdíl mezi těmito příklady je dostatečně popsán v manuálu PHP. Nyní se pojďme podívat, jak by vypadal kód programu, pokud bychom používali více objektů:

<?php
// index.php
require_once 'class_a.php';
require_once 'class_b.php';
$a = new class_a();
$b = new class_b();
?>
<?php
// class_a.php
require_once 'class_c.php';
class a {
  ...
}
?>

V tomto jednoduchém příkladu potřebujeme pracovat s objekty A a B. Objekt A ještě pro svou práci využívá objekt C. Říkáme tedy, že funkčnost objektu A je závislá na objektu C. Tento příklad je přehledný, v adresáři existují vedle souboru index.php i class_a.php, class_b.php a class_c.php. Soubor index.php může být v tomto případě výchozím dokumentem webu, ovšem proč v tomto adresáři vedle něj existují class_a.php, class_b.php a další? Tyto soubory by měly patřit mimo část _public_ našeho webu. Přesuňme je tedy mimo tuto oblast a podívejme se na kód příkladu nyní:

<?php
// index.php
require_once '../../../htprivate/code/class_a.php';
require_once '../../../htprivate/code/class_b.php';
$a = new class_a();
$b = new class_b();
?>
<?php
// class_a.php
require_once '../../../htprivate/code/class_c.php';
class a {
  ...
}
?>

Jak dlouho by nám asi trvalo vyznat se po týdnu v tomto kódu a jak dlouho by to mohlo trvat u rozsáhlého skriptu? Vyvíjíme přece webovou aplikaci, každou chvíli se něco mění a ačkoli máme připravenu analýzu, musíme občas přepisovat kód, který jsme napsali již před dvěma měsíci... Pak se v takových odkazech na soubory těžko orientujeme a odvádíme pozornost jinam. U většího projektu určitě stojí za to situaci řešit. Princip mého řešení je blízký pointrům z C. Nebudu při každé potřebě určitého kódu psát:

<?php
include 'cesta/jmenosouboru.php'
?>

Raději se vždy odkáži na funkci, která to zařídí:

<?php
// index.php
require_once '../../../htprivate/project/code/setup.php';
load_a();
load_b();
$a = new class_a();
$b = new class_b();
?>
<?php
// class_a.php
load_c();
class a {
  ...
}
?>

Nevolám už require_once() (na začátku skriptu ručně načtu jen setup.php), ale volám "načti třídu A!", "načti třídu B!". V programu potřebuji načíst deklaraci tříd a je mi na tomto místě přece jedno, odkud (z jakého souboru) se třída A (respektive třída B) načte. Obě funkce využívají objekt CODE MANAGERA:

<?php
class code_manager {
  var $DIRECTORY_ROOT         = '';
  function code_manager($root = NULL) {
    if (isset($root)):
      $this->set_dirroot($root);
    endif;
  }
  function set_dirroot($root) {
    $this->DIRECTORY_ROOT = $root;
  }
  function prequire($path, $relative = NULL) {
    if (empty($relative)):
      require $this->DIRECTORY_ROOT.$path;
    else:
      require $path;
    endif;
  }
  function prequire_once($path, $relative = NULL) {
    if (empty($relative)):
      require_once $this->DIRECTORY_ROOT.$path;
    else:
      require_once $path;
    endif;
  }
  function test() {
    echo '<pre>';
    print_r(get_required_files());
    echo '</pre>';
  }
}
?>

Metodou test() si potom můžeme ověřit, jaké soubory byly načteny a odladit chyby.

<?php
// setup.php
$code_mng_str = '/Program Files/Apache Group/Apache/htprivate/general/';
$mycode_mng_str = '/Program Files/Apache Group/Apache/htprivate/project/';
require_once ($code_mng_str.'code/class.codemanagement.php');
$code_manager = new code_manager($code_mng_str);
$mycode_manager = new code_manager($mycode_mng_str);
$mycode_manager->prequire_once('code/general.php');
load_template();
?>

Právě na tomto jediném místě se určí cesty do adresářů, kde udržujeme kód PHP programů, knihovny funkcí, deklarace tříd. Objekty CODE MANAGERA lze inicializovat i relativně položenou cestou. Musíme přitom pamatovat, že vždy relativně k veřejně uloženému programu. V souboru, který jsem pojmenoval setup.php rovnou includuji soubor general.php a nástroj pro práci se šablonami. Pokud vím, že tento nástroj používám ve všech programech, nebudu se bát načíst kód již zde:

<?php
// general.php
function load_a() {
  global $mycode_manager;
  load_c();
  $mycode_manager->prequire_once('code/class_a.php');
}
function load_b() {
  global $code_manager;
  $code_manager->prequire_once('code/class_b.php');
}
function load_c() {
  global $code_manager;
  $code_manager->prequire_once('code/class_c.php');
}
function load_template() {
  global $code_manager;
  $code_manager->prequire_once('code/class.template.php');
}
?>

Nyní si to zopakujme. V index.php nejprve načítám setup.php. Zde je uložena absolutní cesta k adresáři general ($code_manager) a project ($mycode_manager). Pro oba adresáře vytvářím instanci objektu CODE MANAGERA. Do adresáře general ukládám všeobecně často užívané deklarace tříd, do adresáře project ukládám takové deklarace, které souvisí jen s daným projektem (může to být například chat, weblog, ankety atd.).

Práci a orientaci dále ulehčí funkce jako load_a(), load_b(), load_c() či load_template(). V případech, kdy jeden objekt využívá druhý a tento je dále závislý na nějakém dalším, se tímto dosáhne elegantního kódu.

Vložení kódu je možné několika způsoby (include, include_once, require, require_once) - v tomto případě se volil require_once(). Analogicky si můžeme definovat metody pinclude() i pinclude_once().

Jelikož se vložení (require_once) kódu provádí v objektu code_manager (přesněji metodou prequire_once), plyne z toho jedno omezení. Nemůžeme totiž například v souboru class_a pracovat s globální proměnnou (objektem, polem apod.) při absenci odkazu na $GLOBALS[]. Z mého pohledu z toho plyne cesta k důslednějšímu OOP. Podívejte se například na soubor db_connect.php (tento kód při načtení CODE MANAGEREM absolutně ztratí smysl):

<?php
$server_name = "localhost";
$db_user = "root";
$db_pass = "sa";
$db_name = "jmeno_databaze";
?>

A nyní tentýž soubor db_connect.php (nyní při použití CODE MANAGERA.. poté pracujeme s objektem $db_connect_info):

<?php
class db_connect_info {
  var $server_name = "localhost";
  var $db_user = "";
  var $db_pass = "";
  var $db_name = "sipky_vyvoj";
}
global $db_connect_info;
$db_connect_info = new db_connect_info();
?>

Tak to je řízení vkládání kódu v PHP podle mého. Zdá se vám tato technika naprosto zbytečná či složitá? Nebo používáte zaběhnutou techniku z příruček pro začátečníky, případně máte svou vlastní? Podělte se o své zkušenosti v diskusi.

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.


Další aktuální články na interval.cz

Tematicky související články

Dejte vědět i ostatním o článku

Diskuse (počet komentářů: 0)

Buďte prvním návštěvníkem, který přidá nový komentář.

Přidat nový komentář

Jméno a e-mail jsou nepovinné. Příspěvky obsahující odkaz jsou moderovány.

Zoner AntiVirus Free pro Android
zabezpečte si svůj smartphone, zdarma
Profesionální eshop Zoner inShop od 990 Kč.
Zoner Photo Studio 14 – vyzkoušejte ZDARMA
Reklama
Reklama
Zoner Photo Studio 14

Syndikace

hledáme nové autory | redakce interval.cz | reklama na interval.cz

© ZONER software, a.s., všechna práva vyhrazena, interval.cz dodržuje právní předpisy o ochraně osobních údajů. Powered by WordPress.