RobotLoader: autoloadowanie klas
RobotLoader to narzędzie, które daje wygodę automatycznego ładowania klas dla całej aplikacji, w tym bibliotek firm trzecich.
- Pozbywamy się wszystkich
require
- zostaną załadowane tylko niezbędne skrypty
- nie wymaga ścisłych konwencji nazewnictwa dla katalogów i plików
Możemy więc zapomnieć o tych znanych nam blokach kodu:
require_once 'Utils/Page.php';
require_once 'Utils/Style.php';
require_once 'Utils/Paginator.php';
// ...
Instalacja
Pobierz i zainstaluj bibliotekę za pomocą Composera:
composer require nette/robot-loader
Korzystanie z
Podobnie jak robot Google indeksuje strony internetowe, RobotLoader przeszukuje wszystkie skrypty PHP i notuje, jakie klasy, interfejsy i cechy w nich znalazł. Następnie buforuje wyniki swojej eksploracji i używa ich w następnym żądaniu. Wystarczy więc określić, które katalogi mają być indeksowane i gdzie mają być buforowane:
$loader = new Nette\Loaders\RobotLoader;
// katalogi, które mają być indeksowane przez RobotLoader (łącznie z podkatalogami)
$loader->addDirectory(__DIR__ . '/app');
$loader->addDirectory(__DIR__ . '/libs');
// ustaw buforowanie w katalogu 'temp'
$loader->setTempDirectory(__DIR__ . '/temp');
$loader->register(); // uruchom RobotLoader
To wszystko, od tej pory nie musimy używać require
. Świetnie!
Jeśli RobotLoader napotka zduplikowaną nazwę klasy podczas indeksowania, rzuca wyjątek i informuje o tym. RobotLoader również automatycznie aktualizuje pamięć podręczną, gdy musi załadować klasę, której nie zna. Zalecamy wyłączenie tego na serwerach produkcyjnych, zobacz Caching.
Jeśli chcesz, aby RobotLoader pominął niektóre katalogi, użyj $loader->excludeDirectory('temp')
(możesz
wykonać wiele połączeń lub przekazać wiele katalogów).
Domyślnie RobotLoader zgłasza błędy w plikach PHP rzucając wyjątek ParseError
. Można to nadpisać za
pomocą $loader->reportParseErrors(false)
.
Aplikacje Nette
Wewnątrz aplikacji Nette, gdzie w pliku startowym używany jest obiekt Bootstrap.php
$configurator
,
notacja może być uproszczona:
$configurator = new Nette\Bootstrap\Configurator;
// ...
$configurator->setTempDirectory(__DIR__ . '/../temp');
$configurator->createRobotLoader()
->addDirectory(__DIR__)
->addDirectory(__DIR__ . '/../libs')
->register();
Analizator plików PHP
RobotLoader może być również użyty do wyszukiwania klas, interfejsów i cech w plikach PHP bez użycia funkcji autoloadingu:
$loader = new Nette\Loaders\RobotLoader;
$loader->addDirectory(__DIR__ . '/app');
// skanuje katalogi w poszukiwaniu klas/interfejsów/traitów
$loader->rebuild();
// zwraca tablicę par class => filename
$res = $loader->getIndexedClasses();
W ten sposób można również wykorzystać cache. Dzięki temu niezmienione pliki nie będą ponownie analizowane przy ponownym skanowaniu:
$loader = new Nette\Loaders\RobotLoader;
$loader->addDirectory(__DIR__ . '/app');
$loader->setTempDirectory(__DIR__ . '/temp');
// skanuje katalogi używając pamięci podręcznej
$loader->refresh();
// zwraca tablicę par class => filename
$res = $loader->getIndexedClasses();
Caching
RobotLoader jest bardzo szybki, ponieważ sprytnie wykorzystuje buforowanie.
Rozwijając się z nim, jesteś praktycznie nieświadomy, że działa on w tle. Stale aktualizuje swoją pamięć podręczną, ponieważ bierze pod uwagę, że klasy i pliki mogą być tworzone, znikać, zmieniać nazwy itp. I nie skanuje wielokrotnie plików, które nie uległy zmianie.
Z drugiej strony, podczas wdrażania na serwerze produkcyjnym, zalecamy wyłączenie aktualizacji pamięci podręcznej za
pomocą $loader->setAutoRefresh(false)
(robi to automatycznie w aplikacji Nette), ponieważ pliki nie ulegają
zmianie. Jednocześnie po wgraniu nowej wersji na hosting konieczne jest wyczyszczenie cache.
Początkowe skanowanie plików, gdy pamięć podręczna jeszcze nie istnieje, może zająć chwilę w przypadku większych aplikacji. RobotLoader ma wbudowane zapobieganie przed cache stampede. Jest to sytuacja, w której duża liczba współbieżnych żądań spotyka się na serwerze produkcyjnym i uruchamia RobotLoader, a ponieważ pamięć podręczna jeszcze nie istnieje, wszystkie zaczęłyby skanować pliki. Co spowodowałoby nieproporcjonalne obciążenie serwera. Na szczęście sposób działania RobotLoader polega na tym, że gdy istnieje wiele współbieżnych żądań, tylko pierwszy wątek indeksuje pliki, tworzy pamięć podręczną, pozostałe czekają, a następnie używają pamięci podręcznej.
PSR-4
Dziś Composer może być używany do autoloadingu, jeśli przestrzega się
PSR-4. Najprościej mówiąc, jest to system, w którym przestrzenie nazw i nazwy klas odpowiadają strukturom katalogów
i nazwom plików, więc na przykład App\Router\RouterFactory
będzie w pliku
/path/to/App/Router/RouterFactory.php
.
RobotLoader nie jest przywiązany do żadnej stałej struktury, więc jest przydatny w sytuacjach, gdy nie czujesz się komfortowo z posiadaniem struktury katalogów zaprojektowanej w taki sam sposób jak przestrzenie nazw PHP, lub gdy rozwijasz aplikację, która historycznie nie używała takich konwencji. Możliwe jest również stosowanie obu ładowarek razem.