Includování souborů v PHP: Která (funkce :-) je ta pravá?

Programujete-li v PHP, určitě znáte čtveřici funkcí include, include_once, require a require_once, které slouží ke vkládání PHP skriptů do sebe. V těch mnoha megabajtech PHP kódu, co dnes po světě provětrávají servery, se běžně vyskytují všechny čtyři. Kterou z těchto funkcí je tedy nejlepší použít ve vašem kódu? S tím vám asi neporadím, ale můžu prozradit, co používám já – a proč.

Nejdřív volba mezi variantami "s once" a "bez once". Tahle volba je pro mě jednoznačná – vyhrává varianta "bez once". Tento způsob vkládání mě totiž donutí promyslet si vrstvy, ze kterých se můj program skládá, a pak do n-té vrstvy vkládat jen soubory z vrstvy n+1. Jen velmi obtížně tak vyrobím program, kde všechno závisí na všem a je to "tak nějak zamotané do sebe". Používání varianty "bez once" je podobně jako třeba checked exceptions v Javě takový malý bič na programátory, aby trochu víc přemýšleli, než začnou psát – s tím rozdílem, že tady je dobrovolný.

Následná volba mezi include a require je pro mě spíš otázkou zvyku. Mezi oběma variantami je totiž jediný rozdíl – když include nenajde daný soubor, vyvolá chybu na úrovni E_WARNING, kdežto require v tomto případě způsobí rovnou E_FATAL_ERROR. Pro mě druh chyby téměř nic neznamená. Chyba na jakékoliv úrovni je prostě chyba a ukazuje, že můj program je špatně – v tomhle jsem nekompromisní. (A také tomu přizpůsobuji nastavení serveru a ošetření chyb se svých skriptech.) Z toho důvodu mi příliš nezáleží na tom, kterou z funkcí použiju – a protože jsem z C/C++ zvyklý na klíčové slovo include, používám ho i v PHP.

To je asi vše, co můžu k tomuto tématu říct. Pokud máte na probíraný problém nějaký jiný názor než tu prezentuji já, rád o něm uslyším v komentářích.

(Malá poznámka nesouvisející s hlavním tématem článku: Jsem přesvědčený, že za můj občas až perfekcionistický přístup k programování, který je asi z tohoto článku trochu cítit, může to, že jsem několik let programoval v Turbo/Borland/Object Pascalu, což je poměrně striktní a programátora v lecčems omezující jazyk. Myslím, že úkol, pro který byl tento jazyk vymyšlen – totiž výuka programování a jeho správných technik – u mě splnil téměř dokonale.)

Jun 22, 2004 – 23:00

Comments

Tomas S.
Tomas S.
Jeste o jednom rozdilu vim a to kdyz (uznavam nepriliz hezky) napisu include ci require do cyklu. include se provede vzdy,zatimco require se provede jen jednou(ale kod samozrejme tolikrat kolikrat je potreba), toto plati pro PHP az do verze 4.0.2. ale je jeste dost lidi,kteri v tom pisi.
dgx
dgx
Ahoj, Tvuj nekompromisní přístup k programování se mi velmi líbí, webík si dávám do bookmarku :-)

Při volbě mezi require | require_once | include | include_once jsem vycházel z podobných myšlenek, ale výsledek bych zcela jiný: require_once. Hned vysvětlím proč:

1) Protože je pro mě jakákoliv chyba také vždy fatalní, tak nechci, aby se po jejím výskytu dále (a nepředvídatelně) prováděl script. Require ho utne. Možná toho lze docílit i změnou konfigurace PHP, ale tu často nemůžu ovlivnit.

2) V OOP obvykle píšu třídy do samostatných souborů, je pak docela časté, že různé třídy využívají zase jiné třídy atd. A žádná třída se samozřejmě nemůže parsovat vícekrát. Tudíž jediné řešení je ..._once

[1] provádět include nebo require v cyklu je docela zhovadilost, nemyslíš?
David Majda
[2] 1) Já do svých webů dávám vlastní chybový handler a ten to utne vždycky. Popravdě řečeno, umí toho docela u trochu víc, někdy se o tom možná rozepíšu podrobněji.

2) Já své třídy sdružuju do modulů jejichž součástí je vždy soubor includes.php, který třídy naincluduje ve správném pořadí. Klienti modulu jen includují includes.php a dál se nestarají. Celé _once je IMHO hlavně otázka lenosti organizovat pořádně kód. Možná ale někde existuje malé procento opravdu oprávněných případů (nicméně ještě jsem takový neviděl).
cita
[2] ad.2 U OOP máte možnost využít magickou fci __autoload().

př. mého kódu:

function __autoload($className)
{
try {
if(!@include_once($className.CLASS_EXT))
throw new Exception('Cannot include '.$className);
} catch (Exception $e) {
trigger_error('Cannot load class '.$className.' . '.$e->getMessage(), E_USER_ERROR);
}

}

Add comment

It is not possible to add comments to posts older than one month.