Jedním z drobných úskalí webového vývoje, které ale spolehlivě zamotá hlavu drtivé většině začátečníků je relativní adresace. V menších projektech je ještě reálné pracovat s relativními cestami k souborům, ale ve větších projektech (Kdo z nás chce pořád sbírat jen drobky?) je situace reálně neudržitelná. Já jsem před lety začal používat absolutní cesty a musím přiznat, že mám konečně klid.
První zádrhel se skrývá v include/require souborů, pokud se používají relativní cesty, je nutné si pamatovat, že pokud se includuje do hloubky, tj. includované soubory includují něco dalšího, počítá se cesta vůči prvnímu scriptu, tj. tomu, který je obvykle v URL (pokud používáte PHP jako CLI, tak se vše počítá vůči scriptu, který jste spustili z příkazové řádky).
Představte si následující uspořádání souborů:
|--admin | |_index.php | |_summary.php |--css | |_sprava.css | |_prezentace.css |--init | |_configure.php | |_init.php |--knihovny | |_auth.php | |_db.php | |_mail.php | |_inputs.php |_index.php |_read.php
V souboru index.php
v kořenovém adresáři je sekvence:
<?php require_once './init/configure.php'; require_once './init/init.php'; …
Script configure.php
obsahuje nějaké základní údaje, třeba konfiguraci databáze, nebo často používané vzory pro regulární výrazy. Scrip init.php
se postará o natažení potředných knihoven a inicializaci připojení k databázi, může vypadat třeba takto:
<?php require_once './lib/auth.php'; require_once './lib/db.php'; require_once './lib/inputs.php'; $db=new db(…); … ?>
Vypadá to jasně, ale při pokusu o týž postup z adresáře admin
nastane problém. Require v prvním zdrojovém kódu by byl o něco delší, příklad by vypadal následovně:
<?php require_once './../init/configure.php'; require_once './../init/init.php'; …
Sekvence je zřejmá. Začátek „./
“ znamená že se má začít v adresáři, kde je script, který jste spustili, tato část není povinná. Část „../
“ znamená, že z aktuálního adresáře je třeba sledovat další cestu o adresář výše (tj. v tomto případě se nemá další cesta hledat v adresáři admin
, ale v kořenovém adresáři). No a zbytek sekvence je snad zřejmý každému. Problém nastává v případě nataženého souboru init.php
už problém nastává, protože ten se bude snažit otevítat několik dalších knihoven, ale jak jsem napsal, cestase bude odvozovat od prvního scriptu, takže PHP interpret se bude snažit otevítat soubor admin/lib/auth.php
, ale ten tam přeci není.
Z této problematiky existují tři způsoby úniku, buď budou stránky soubory stránek unístěné v adresáři „www“, nebo veškeré knihovny budou nakopírovány i v adresáři admin/
, což při dnešních parametrech webhostingů nepředstavuje problém, ale je to nesystémové, protože po úpravě jedné knihovny je třeba zajistit její synchronizaci na dalším místě. Poslední variantou, a při složitějším projektu jedinou reálně použitelnou, je používání absolutních cest.
Pro zjištění toho, v jakém adresáři je script uložen mi slouží triviální sekvence příkazů v PHP:
echo $config['path'] = dirname(__FILE__).'/<br>'; echo 'http://'.$_SERVER['HTTP_HOST'].str_replace('bblog/install.php','',$_SERVER['REQUEST_URI']).'<br />';
Tato sekvence mi zobrazí malinko více informací, než se potřebuji, ale s tím si už snadno poradím. Během prvního nastavovaání nové prezentace si tuto sekvenci, v souboru install.php, umístím do kořenového adresáře, do url přidám za doménu název scriptu, tj. například http://www.abecedahracek.cz/install.php a do souboru config zapíši hodnoty absolutního URL (tj. řádek, který začíná písmenky http
) a absolutní cesty (na Un*xovém serveru bude tato část začínat lomítkem, na Windowsovém (asi, fakt nepoužívám Win server) písmenkem disku).
Poté už je přepis obou ukázek zdrojových kódů snad zřejmý:
<?php require_once './init/configure.php'; require_once $abspath . 'init/init.php'; … <?php require_once $abspath . 'lib/auth.php'; require_once $abspath . 'lib/db.php'; require_once $abspath . 'lib/inputs.php'; $db=new db(…); … ?>
Článek popisoval jen problematiku relativních a absolutních cest v kontextu souborů, ale situace adresách (URL) je identická, praktičtější je použít možností absolutního URL, protože třeba jen konfigurace mého oblíbeného FCKEditoru je s použitím relativních cest a adres docela slušně adrenalinovou a neprůhlednou záležitostí.
Napsat komentář