RobotLoader: autoloading klas
RobotLoader to narzędzie, które zapewni Ci komfort automatycznego ładowania klas dla całej Twojej aplikacji, włącznie z bibliotekami stron trzecich.
- pozbędziemy się wszystkich
require
- będą ładowane tylko potrzebne skrypty
- nie wymaga ścisłych konwencji nazewnictwa katalogów czy plików
- ekstremalnie szybki
- żadnych ręcznych aktualizacji pamięci podręcznej, wszystko odbywa się automatycznie
- dojrzała, stabilna i szeroko stosowana biblioteka
Możemy więc zapomnieć o tych znanych blokach kodu:
require_once 'Utils/Page.php';
require_once 'Utils/Style.php';
require_once 'Utils/Paginator.php';
// ...
Instalacja
RobotLoader można pobrać jako jeden samodzielny plik
RobotLoader.php
, który wstawisz za pomocą require
do swojego skryptu i od razu masz do dyspozycji
komfortowy autoloading dla całej aplikacji.
require '/path/to/RobotLoader.php';
$loader = new Nette\Loaders\RobotLoader;
// ...
Jeśli budujesz aplikację wykorzystującą Composer, możesz go zainstalować za pomocą niego:
composer require nette/robot-loader
Użycie
Podobnie jak robot Google przeszukuje i indeksuje strony internetowe, tak i RobotLoader przeszukuje wszystkie skrypty PHP i zapisuje, które klasy, interfejsy, traity i enumy w nich znalazł. Wyniki badań następnie zapisuje do cache i używa przy następnym żądaniu. Wystarczy więc określić, które katalogi ma przeszukiwać i gdzie zapisywać cache:
$loader = new Nette\Loaders\RobotLoader;
// katalogi, które RobotLoader ma indeksować (włącznie z podkatalogami)
$loader->addDirectory(__DIR__ . '/app');
$loader->addDirectory(__DIR__ . '/libs');
// ustawiamy cachowanie w katalogu 'temp'
$loader->setTempDirectory(__DIR__ . '/temp');
$loader->register(); // uruchamiamy RobotLoader
I to wszystko, od tej chwili nie musimy używać require
. Super!
Jeśli RobotLoader napotka podczas indeksowania zduplikowaną nazwę klasy, rzuci wyjątek i poinformuje Cię o tym. RobotLoader również automatycznie aktualizuje cache, gdy ma załadować klasę, której nie zna. Zalecamy wyłączenie tej funkcji na serwerach produkcyjnych, zobacz Cachowanie.
Jeśli chcesz, aby RobotLoader pominął niektóre katalogi, użyj $loader->excludeDirectory('temp')
(można
wywoływać wielokrotnie lub przekazać więcej katalogów).
Domyślnie RobotLoader zgłasza błędy w plikach PHP rzucając wyjątek ParseError
. Można to pominąć za
pomocą $loader->reportParseErrors(false)
.
Aplikacja Nette
Wewnątrz aplikacji Nette, gdzie w pliku startowym Bootstrap.php
używany jest obiekt $configurator
,
zapis można uprościć:
$configurator = new Nette\Bootstrap\Configurator;
// ...
$configurator->setTempDirectory(__DIR__ . '/../temp');
$configurator->createRobotLoader()
->addDirectory(__DIR__)
->addDirectory(__DIR__ . '/../libs')
->register();
Analizator plików PHP
RobotLoader można również użyć wyłącznie do wyszukiwania klas, interfejsów, traitów i enumów w plikach PHP bez wykorzystywania funkcji autoloadingu:
$loader = new Nette\Loaders\RobotLoader;
$loader->addDirectory(__DIR__ . '/app');
// przeszukuje katalogi w poszukiwaniu klas / interfejsów / traitów / enumów
$loader->rebuild();
// zwraca tablicę par klasa => nazwa pliku
$res = $loader->getIndexedClasses();
Nawet przy takim użyciu można wykorzystać cache. Dzięki temu przy ponownym skanowaniu nie będą ponownie analizowane niezmienione pliki:
$loader = new Nette\Loaders\RobotLoader;
$loader->addDirectory(__DIR__ . '/app');
// ustawiamy cachowanie w katalogu 'temp'
$loader->setTempDirectory(__DIR__ . '/temp');
// przeszukuje katalogi z wykorzystaniem cache
$loader->refresh();
// zwraca tablicę par klasa => nazwa pliku
$res = $loader->getIndexedClasses();
Cachowanie
RobotLoader jest bardzo szybki, ponieważ sprytnie wykorzystuje cache.
Podczas rozwoju praktycznie nie zauważasz, że działa w tle. Bieżąco aktualizuje cache, ponieważ zakłada, że klasy i pliki mogą powstawać, znikać, zmieniać nazwy itp. I nie skanuje ponownie plików, które się nie zmieniły.
Podczas wdrażania na serwerze produkcyjnym zalecamy natomiast wyłączenie aktualizacji cache za pomocą
$loader->setAutoRefresh(false)
(w aplikacji Nette dzieje się tak automatycznie), ponieważ pliki się nie
zmieniają. Jednocześnie konieczne jest wtedy przy wgrywaniu nowej wersji na hosting usunięcie cache.
Pierwsze skanowanie plików, gdy cache jeszcze nie istnieje, może w przypadku większych aplikacji oczywiście chwilę potrwać. RobotLoader ma wbudowaną prewencję przed cache stampede. Jest to sytuacja, gdy na serwerze produkcyjnym pojawi się większa liczba równoczesnych żądań, które uruchomią RobotLoader, a ponieważ cache jeszcze nie istnieje, wszystkie zaczęłyby skanować pliki. Co nieproporcjonalnie obciążyłoby serwer. Na szczęście RobotLoader działa tak, że przy wielu równoczesnych żądaniach pliki indeksuje tylko pierwszy wątek, tworzy cache, pozostałe czekają, a następnie wykorzystują cache.
PSR-4
Obecnie można do autoloadingu używać
Composera przy zachowaniu PSR-4. Upraszczając, jest to system, w którym przestrzenie nazw i nazwy klas odpowiadają
strukturze katalogów i nazwom plików, czyli np. App\Core\RouterFactory
będzie w pliku
/path/to/App/Core/RouterFactory.php
.
RobotLoader nie jest związany z żadną stałą strukturą, dlatego przydaje się w sytuacjach, gdy nie do końca odpowiada Ci posiadanie tak samo zaprojektowanej struktury katalogów jak przestrzenie nazw w PHP, lub gdy rozwijasz aplikację, która historycznie takich konwencji nie wykorzystuje. Możliwe jest również używanie obu loaderów jednocześnie.