[ Webhosting profitux.cz ]
v6ak [ programování, bezpečnost, web, php, java, ... ] (Vít Šesták)
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.

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 (https://commoncrawl.org/faq/) time:0.61277800 1544877405
web
mail
comment