Nette RobotLoader

RobotLoader to narzędzie dające komfort automatycznego wczytywania klas dla całej Twojej aplikacji, wraz z bibliotekami zewnętrznymi.

  • Eliminuje wszystkie instrukcje require
  • Wczytywane są tylko potrzebne skrypty
  • Nie wymaga ścisłych konwencji nazewniczych katalogów ani plików
  • Niezwykle szybki
  • Żadnych ręcznych aktualizacji cache; wszystko dzieje się automatycznie
  • Dojrzała, stabilna i szeroko używana biblioteka

Możemy więc zapomnieć o tych znajomych blokach kodu:

require_once 'Utils/Page.php';
require_once 'Utils/Style.php';
require_once 'Utils/Paginator.php';
// ...

Instalacja

RobotLoadera możesz pobrać jako pojedynczy samodzielny plik RobotLoader.php, dołączyć go w swoim skrypcie przez require i natychmiast cieszyć się wygodnym autoloadingiem dla całej aplikacji.

require '/path/to/RobotLoader.php';

$loader = new Nette\Loaders\RobotLoader;
// ...

Jeśli budujesz aplikację za pomocą Composera, możesz zainstalować go przez:

composer require nette/robot-loader

Użycie

Podobnie jak robot Google przemierza i indeksuje strony internetowe, RobotLoader przechodzi wszystkie skrypty PHP i zapisuje, jakie klasy, interfejsy, traity i enumy znalazł. Następnie przechowuje te znaleziska w cache i używa ich przy kolejnych żądaniach. Musisz tylko podać, które katalogi ma skanować i gdzie przechowywać cache:

$loader = new Nette\Loaders\RobotLoader;

// Katalogi, które RobotLoader ma zindeksować (wraz z podkatalogami)
$loader->addDirectory(__DIR__ . '/app');
$loader->addDirectory(__DIR__ . '/libs');

// Ustawiamy buforowanie do katalogu 'temp'
$loader->setTempDirectory(__DIR__ . '/temp');
$loader->register(); // Aktywujemy RobotLoadera

I to wszystko! Od tego momentu nie musisz używać require. Świetnie!

Jeśli RobotLoader natrafi przy indeksowaniu na zduplikowaną nazwę klasy, rzuci wyjątek i Cię powiadomi. RobotLoader automatycznie aktualizuje też cache, gdy musi wczytać klasę, której nie zna. Zalecamy wyłączenie tego na serwerach produkcyjnych, patrz Buforowanie.

Jeśli chcesz, żeby RobotLoader pomijał pewne katalogi, użyj $loader->excludeDirectory('temp') (można wywołać wielokrotnie albo przekazać wiele katalogów).

Domyślnie RobotLoader skanuje tylko pliki z rozszerzeniem .php. Żeby zindeksować także inne typy plików, dostosuj właściwość $acceptFiles trzymającą tablicę masek:

$loader->acceptFiles = ['*.php', '*.inc'];

Właściwość $ignoreDirs trzyma podobnie maski katalogów, które przy skanowaniu są zawsze pomijane (domyślnie .*, *.old, *.bak, *.tmp, temp).

Domyślnie RobotLoader zgłasza błędy w plikach PHP, rzucając wyjątek ParseError. Da się to wyciszyć przez $loader->reportParseErrors(false).

Pod maską register() podpina metodę tryLoad() do łańcucha autoloadingu PHP. Zawsze, gdy PHP potrzebuje nieznanej klasy, interfejsu, traitu albo enuma, przekazuje nazwę do $loader->tryLoad($type), która znajduje pasujący plik i go dołącza.

Nette Application

Wewnątrz Nette Application, gdzie w pliku rozruchowym Bootstrap.php używany jest obiekt $configurator, ustawienie da się uprościć:

$configurator = new Nette\Bootstrap\Configurator;
// ...
$configurator->setTempDirectory(__DIR__ . '/../temp');
$configurator->createRobotLoader()
	->addDirectory(__DIR__)
	->addDirectory(__DIR__ . '/../libs')
	->register();

Analizator plików PHP

RobotLoadera można też używać wyłącznie do znajdowania klas, interfejsów, traitów i enumów w plikach PHP bez używania funkcji autoloadingu:

$loader = new Nette\Loaders\RobotLoader;
$loader->addDirectory(__DIR__ . '/app');

// Skanuje 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żesz wykorzystać buforowanie. Zapewnia ono, że niezmienione pliki nie będą skanowane ponownie:

$loader = new Nette\Loaders\RobotLoader;
$loader->addDirectory(__DIR__ . '/app');

// Ustawiamy buforowanie do katalogu 'temp'
$loader->setTempDirectory(__DIR__ . '/temp');

// Skanuje katalogi z użyciem cache
$loader->refresh();

// Zwraca tablicę par klasa => nazwa pliku
$res = $loader->getIndexedClasses();

Buforowanie

RobotLoader jest bardzo szybki, bo sprytnie wykorzystuje buforowanie.

Podczas tworzenia ledwie zauważasz, że działa w tle. Na bieżąco aktualizuje swoją cache, przewidując, że klasy i pliki mogą powstawać, być usuwane, przemianowywane itd. I nie skanuje ponownie plików, które się nie zmieniły.

Na serwerze produkcyjnym odwrotnie: zalecamy wyłączenie aktualizacji cache przez $loader->setAutoRefresh(false) (w Nette Application dzieje się to automatycznie), bo pliki się nie zmieniają. Jednocześnie trzeba wyczyścić cache przy wgrywaniu nowej wersji na hosting.

Początkowe skanowanie plików, gdy cache jeszcze nie istnieje, może przy większych aplikacjach naturalnie chwilę potrwać. RobotLoader ma wbudowane zabezpieczenie przed cache stampede. To sytuacja, w której duża liczba równoległych żądań na serwerze produkcyjnym uruchamia RobotLoadera, a ponieważ cache jeszcze nie istnieje, wszystkie zaczęłyby skanować pliki, potencjalnie przeciążając serwer. Na szczęście RobotLoader działa tak, że przy wielu równoległych żądaniach pliki indeksuje i cache tworzy tylko pierwszy wątek, a pozostałe czekają i potem używają wygenerowanej cache.

PSR-4

Dziś do autoloadingu możesz używać Composera, trzymając się PSR-4. Upraszczając, to system, w którym przestrzenie nazw i nazwy klas odpowiadają strukturze katalogów i nazwom plików, np. App\Core\RouterFactory będzie w pliku /ścieżka/do/App/Core/RouterFactory.php.

RobotLoader nie jest przywiązany do żadnej ustalonej struktury, więc przydaje się w sytuacjach, gdy nie chcesz, żeby struktura katalogów dokładnie odpowiadała przestrzeniom nazw PHP, albo gdy rozwijasz aplikację, która historycznie takich konwencji nie używa. Da się też używać obu loaderów razem.

Jeśli aktualizujesz do nowszej wersji, zajrzyj na stronę aktualizacji.

wersja: 4.x