Jestem pewien, że to wiesz, kiedy programując skrypty PHP, dzielimy kod na wiele plików i aby mieć dostępne wszystkie części, ładujemy je za pomocą serii wywołań `include`, `require` lub najlepiej `require_once`, co gwarantuje załadowanie tylko raz.
W kodzie wygląda to następująco:
require_once 'Router.php';require_once 'Strona.php';require_once 'Paginator.php';
Główną wadą tego podejścia jest to, że programista musi stale upewniać się, że wszystko jest zawsze załadowane. Jeśli jednak użytkownik dużo ładuje, niepotrzebnie traci wydajność i wielokrotnie trafia na dysk. Z rozwiązaniem podręcznikowym wiążą się więc same problemy.
Na szczęście w PHP istnieje natywne wsparcie dla tak zwanego Class Autoloading, czyli logiki w kodzie, która ładuje plik klasy tylko wtedy, gdy jest on po raz pierwszy potrzebny (zazwyczaj przy pierwszym utworzeniu instancji).
Prosta implementacja może wyglądać następująco:
spl_autoload_register(function (string $className): void {include 'src/' . $className . '.php';});$obj = new MyClass1();$obj2 = new MyClass2();
Podczas tworzenia instancji klasy MyClass1
, funkcja spl_autoload_register
odczytuje plik MyClass1.php
z katalogu src
. W tej implementacji przyjęto, że każda klasa znajduje się w osobnym pliku nazwanym według nazwy klasy lub interfejsu.
W rzeczywistych zastosowaniach może wystąpić wiele nieprzyjemnych sytuacji, które komplikują na przykład pracę w trybie autoload:
Nie musimy jednak w tym celu programować własnego rozwiązania, lecz możemy wykorzystać istniejące, raz zaprojektowane.
Jeśli używasz Composera, prawdopodobnie korzystasz również z jego natywnego autoloadingu. Dzieje się tak, ponieważ podczas instalacji dowolnego pakietu Composer automatycznie generuje mapę klas
, która jest przeglądem klas i ich fizycznych lokalizacji.
Następnie na początku kodu (zwykle w index.php
) wystarczy użyć:
require __DIR__ . '/vendor/autoload.php';
Jednak autoloading jest generowany tylko raz, gdy wywoływana jest komenda composer dump
, więc konieczne jest regenerowanie autoloadingu za każdym razem, gdy aplikacja się zmienia.
Do lokalnego rozwoju bardzo lubię pakiet nette/robot-loader
, który automatycznie przemierza strukturę katalogów i buforuje lokalizacje klas. Jeśli więc wczytujemy klasę, najpierw sprawdzana jest ona w pamięci podręcznej, a dopiero jeśli nie istnieje, następuje automatyczne przeindeksowanie projektu. W związku z tym programista nie musi w ogóle śledzić, gdzie znajduje się dany plik lub klasa, i po prostu programuje.
Instalacja za pomocą aplikacji Composer:
composer require nette/robot-loader
Podstawowe objaśnienia funkcji są opisane w samej dokumentacji:
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 swoich badań i wykorzystuje je w następnym żądaniu. Wystarczy więc określić, które katalogi mają być indeksowane i gdzie mają być buforowane.
Jest on wtedy niezwykle łatwy w użyciu:
$loader = new Nette\Loaders\RobotLoader;// dodaj katalogi, które RobotLoader ma indeksować$loader->addDirectory(__DIR__ . '/app');$loader->addDirectory(__DIR__ . '/libs');// ustaw buforowanie na dysku w katalogu 'temp'.$loader->setTempDirectory(__DIR__ . '/temp');$loader->register(); // uruchom RobotLoader
Ustawienie $loader->setAutoRefresh(true lub false)
określa, czy RobotLoader powinien przeindeksować pliki, gdy napotka nową klasę. Ta funkcja powinna być wyłączona na serwerach produkcyjnych.
Teraz już nigdy więcej nie będziesz musiał zmagać się z automatycznym ładowaniem.
Podczas tworzenia prawdziwego projektu stosuję rozwiązanie łączone.
W praktyce wygląda to tak, że ładuję zainstalowane pakiety przez Composer autoload (który jest bardzo wydajny) i to rozwiązuje problem ładowania wszystkich klas w katalogu vendor
.
Kod dla danego projektu jest następnie umieszczany w katalogu app
, gdzie za pomocą RobotLoader automatycznie ładuję tylko kilka klas. Ważne jest, aby konkretna aplikacja była jak najmniejsza i w jak największym stopniu korzystała z gotowych pakietów - to bardzo ułatwia ponowne wykorzystanie.
Struktura projektu wygląda następująco:
/appBootstrap.php <-- konfigurace/modelUserForm.php <-- projektové třídyRegisterFactory.php.../vendor... <-- knihovny/wwwindex.php <-- inicializace
Czasami może się zdarzyć, że nie wszystkie pliki zostaną załadowane i pojawią się problemy.
Do debugowania zalecam użycie funkcji get_included_files().
Jan Barášek Více o autorovi
Autor článku pracuje jako seniorní vývojář a software architekt v Praze. Navrhuje a spravuje velké webové aplikace, které znáte a používáte. Od roku 2009 nabral bohaté zkušenosti, které tímto webem předává dál.
Rád vám pomůžu:
Články píše Jan Barášek © 2009-2024 | Kontakt | Mapa webu
Status | Aktualizováno: ... | pl