[ Webhosting profitux.cz ]
v6ak [ programování, bezpečnost, web, php, java, ... ] (Vít Šesták)
Buzz - v6ak Twitter - v6ak

štítky

Jak by měl vypadat každý autoload

Autoload je v PHP 5 populární a pokud nepatříte k začátečníkům v PHP 5, pak ho pravěpodobně aspoň trochu znáte. Umožňuje načíst třídu až když je potřeba. Jenže autoload se může stát zdrojem problémů a "střetu dvou kultur". Ale nemusí. Pojďmě se podívat, jak střetům a jiným problémům zabránit.

Jednoduchý střet

Pokud nerozumíte, ukážu vám jednoduchý střet. Jeden programátor bude psát třeba nějaký framework a vytvoří si jednoduchý špatný autoload:

function __autoload($c){ include str_replace('_', '/', $c).'.php'; };

Nejdřív ten možný střet: pokud si takto vytvoří autoload dva různé frameworky, nemůže to skončit jinak než fatal errorem, pokud jsou na jedné stránce požity oba. U každé normální knihovny by to při dodržování nějaké formy namspaces nebyl problém - bez problémů může existovat Zend_Form a v6_form vedle sebe. Ale tady žádné namespaces nejsou.

Další problém je, že je mnohem obtížnější ze skriptu vytáhnout všechny knihovny, na kterých závisí. A bez znalosti dané autoloadové logiky úplně nemožné. (Dobře, tu nemožnost tady nevyřeším, ale můžu to zjednodušit.) Já jsem kdysi psal automatizovaný updater, který umožňoval mít knihovny pro více projektů v jednom adresáři. (A někdy se k tomu snad vrátím a dopíšu. :-) ) Tímto byste ho poněkud degradovali.

A snad už poslední problém je, že chybějící knihovnu odhalíte až za běhu.

Ták, teď jsem ukázal, jak by autoload neměl vypadat. A hned se podívám na druhou stranu - jak by (obecně) měl vypadat.

Požadavky na autoload

Lze jednoduše určit potenciálně potřebné soubory bez spouštění skriptu.

Toho dosáhneme jednoduše: autoload bude volat nějakou metodu nebo funkci, když bude chtít přidat soubor k potenciálnímu načtení. Může to vypadat třeba vendor_autoload::addClass('vendor_a_class') nebo vendor_autoload::addFile('vendor_a_class', 'path/to/a/class.php'). Pro nějaký updater, jako jsem chtěl vytvořit, by případně někdy mohl poskytnout třídu.

Detekuje neexistující třídy co nejdříve.

Po splnění předchozího bodu stačí již v metodě addClass nebo addFile kontrolovat existenci souboru. Pravda, nezkontroluje to případ, kdy soubor a.php řekne autoloadu, že chce v případě potřeby includovat b.php, jenže b.php se odkazuje na neexistující c.php. To je ale daň za autoload.

Umí spoluracovat i s dalšími autoloady

To je velmi důležité. Předně musí místo __autoload použít spl_autoload_register. Ale to není všechno.

Jak má autoload reagovat, když nemá co načíst?

Některé autoloady používají triky na vrhnutí výjimky, pokud nemají co načíst, jiné skončí warningem nebo fatal errorem u příkazu include/require[_once]. To ale není moudré. Obecně se autoload nemůže spoléhat, že je volaný jako poslední. Pokud tedy nemůže načíst danou třídu, neměl by dělat nic, čímž dá šanci dalšímu autoloadu v řadě.

Funguje i při vypnutém autoloadu

Autoload může být vypnutý, jako například v CLI interactive mode, funkce spl_autoload_register nemusí být v dané verzi php5 dostupná nebo může být php bez spl. To jsou všechno problémy, se kterými se můžete setkat. Určitě bych nevynechal podmínku function_exists('spl_autoload_register'). Na CLI interactive mode se můžete buď vykašlat a odkázat programátory na phell, nebo asi i lze nějak detekovat, anebo můžete prostě vyzkoušet, zda autoload funguje a podle toho se rozhodnout.

Co si naopak autoload může dovolit

Nejjednodušší autoload

Tedy samotný autoload může v nejjednodušším případě podle mého názoru vypadat nějak takto:

public static function autoload($class){ if(isset(self::$loadMap[$clas­s])){ require self::$loadMap[$clas­s]; }; }

Je to pochopitelně jen útržek kódu, je potřeba přidat ještě další metody.

Diskuzi ke článku naleznete zde.

Linkování

Líbí se Vám tato stránka? Zalinkujte ji!

Chcete sledovat novinky? Pokud si právě prohlížíte článek a hledáte RSS pro celý web, pak jste trošku jinde. Možná hledáte poslední změny.

Validní HTML 4.01 StrictValidní CSS 2.0Validní hlavní RSS kanálPHP 5Apache
referer: UA:CCBot/2.0 (http://commoncrawl.org/faq/) time:0.68951600 1498484755
web
mail
comment