RobotLoader: autoloading tříd
RobotLoader je nástroj, který vám zajistí komfort automatického načítání tříd pro celou vaši aplikaci včetně knihoven třetích stran.
- zbavíme se všech
require
- budou se načítat jen potřebné skripty
- nevyžaduje striktní konvence pojmenování adresářů či souborů
- extrémně rychlé
- žádné ruční aktualizace mezipaměti, vše probíhá automaticky
- zralá, stabilní a široce používaná knihovna
Můžeme tedy zapomenout na tyto známé bloky kódu:
require_once 'Utils/Page.php';
require_once 'Utils/Style.php';
require_once 'Utils/Paginator.php';
// ...
Instalace
RobotLoader si můžete stáhnout jako jeden samostatný soubor
RobotLoader.php
, který vložíte pomocí require
do svého skriptu a hned máte k dispozici
komfortní autoloading pro celou aplikaci.
require '/path/to/RobotLoader.php';
$loader = new Nette\Loaders\RobotLoader;
// ...
Pokud stavíte aplikaci využívající Composer, můžete jej nainstalovat pomocí něj:
composer require nette/robot-loader
Použití
Podobně, jako Google robot prochází a indexuje webové stránky, tak i RobotLoader prochází všechny PHP skripty a zaznamenává si, které třídy, rozhraní, traity a enumy v nich našel. Výsledky bádání si poté uloží do cache a použije při dalším požadavku. Stačí tedy určit, které adresáře má procházet a kam ukládat cache:
$loader = new Nette\Loaders\RobotLoader;
// adresáře, které má RobotLoader indexovat (včetně podadresářů)
$loader->addDirectory(__DIR__ . '/app');
$loader->addDirectory(__DIR__ . '/libs');
// nastavíme cachování do adresáře 'temp'
$loader->setTempDirectory(__DIR__ . '/temp');
$loader->register(); // spustíme RobotLoader
A to je vše, od této chvíle nemusíme používat require
. Paráda!
Pokud RobotLoader narazí při indexaci na duplicitní název třídy, vyhodí výjimku a informuje vás o tom. RobotLoader také automaticky aktualizuje cache, když má načíst třídu, kterou nezná. To doporučujeme vypnout na produkčních serverech, viz Cachování.
Pokud chcete, aby RobotLoader přeskočil nějaké adresáře, použijte $loader->excludeDirectory('temp')
(lze
volat vícenásobně nebo předat více adresářů).
Ve výchozím nastavení RobotLoader hlásí chyby v souborech PHP vyhozením výjimky ParseError
. To lze
potlačit pomocí $loader->reportParseErrors(false)
.
Nette aplikace
Uvnitř Nette aplikace, kde se používá v zaváděcím souboru Bootstrap.php
objekt $configurator
,
lze zápis zjednodušit:
$configurator = new Nette\Bootstrap\Configurator;
// ...
$configurator->setTempDirectory(__DIR__ . '/../temp');
$configurator->createRobotLoader()
->addDirectory(__DIR__)
->addDirectory(__DIR__ . '/../libs')
->register();
Analyzátor PHP souborů
RobotLoader lze také použít čistě k vyhledávání tříd, rozhraní, trait a enumů v souborech PHP bez využívání funkce autoloadingu:
$loader = new Nette\Loaders\RobotLoader;
$loader->addDirectory(__DIR__ . '/app');
// prohledá adresáře na třídy / rozhraní / traity / enumy
$loader->rebuild();
// vrací pole dvojic třída => název souboru
$res = $loader->getIndexedClasses();
I při takovém použití můžete využít cache. Díky tomu při opětovném skenování nebudou opakovaně analyzovány nezměněné soubory:
$loader = new Nette\Loaders\RobotLoader;
$loader->addDirectory(__DIR__ . '/app');
// nastavíme cachování do adresáře 'temp'
$loader->setTempDirectory(__DIR__ . '/temp');
// prohledá adresáře s využitím cache
$loader->refresh();
// vrací pole dvojic třída => název souboru
$res = $loader->getIndexedClasses();
Cachování
RobotLoader je velice rychlý, protože šikovně využívá cache.
Při vývoji s ním prakticky netušíte, že běží na pozadí. Průběžně si aktualizuje cache, protože počítá s tím, že třídy a soubory mohou vznikat, zanikat, přejmenovávat se, atd. A opakovaně nescanuje soubory, které se nezměnily.
Při nasazení na produkčním serveru naopak doporučujeme aktualizaci cache vypnout pomocí
$loader->setAutoRefresh(false)
(v Nette Aplikaci se tak děje automaticky), protože soubory se nemění.
Zároveň je pak nutné při nahrání nové verze na hostingu smazat cache.
Prvotní scanování souborů, když cache ještě neexistuje, může u rozsáhlejších aplikací pochopitelně chviličku trvat. RobotLoader má vestavěnou prevenci před cache stampede. Jde o situaci, kdy se na produkčním serveru sejde větší počet souběžných požadavků, které spustí RobotLoader, a protože cache ještě neexistuje, začaly by všechny scanovat soubory. Což by neúměrně zatížilo server. Naštěstí RobotLoader funguje tak, že při více souběžných požadavcích indexuje soubory pouze první vlákno, vytvoří cache, ostatní čekají a následně cache využíjí.
PSR-4
Dnes lze pro autoloading používat Composer při dodržení
PSR-4. Zjednodušeně řečeno jde o systém, kdy jmenné prostory a názvy tříd odpovídají adresářové struktuře a
názvům souborů, tedy např. App\Core\RouterFactory
bude v souboru
/path/to/App/Core/RouterFactory.php
.
RobotLoader není s žádnou pevnou strukturou spjat, proto se hodí v situacích, kdy vám úplně nevyhovuje mít stejně navrženou adresářovou strukturu jako jmenné prostory v PHP, nebo když vyvíjíte aplikaci, která historicky takové konvence nevyužívá. Je možné také používat oba loadery dohromady.