Я впевнений, що ви знаєте, що при програмуванні PHP-скриптів ми розбиваємо код на багато файлів і, щоб мати всі частини доступними, завантажуємо їх серією викликів `include`, `require` або краще `require_once`, що гарантує завантаження тільки один раз.
У коді це виглядає так:
require_once 'Router.php';require_once 'Page.php';require_once 'Paginator.php';
Основним недоліком такого підходу є те, що програмісту доводиться постійно стежити за тим, щоб все завжди було завантажено. Але якщо він сильно навантажується, то невиправдано втрачає продуктивність і багато разів звертається до диска. Тому ручне рішення має лише проблеми.
На щастя, в PHP є вбудована підтримка так званого автозавантаження класів, тобто логіки в коді, яка завантажує файл класу тільки тоді, коли він вперше потрібен (зазвичай при першому створенні екземпляра).
Проста реалізація може виглядати наступним чином:
spl_autoload_register(function (string $className): void {include 'src/' . $className . '.php';});$obj = new MyClass1();$obj2 = new MyClass2();
При створенні екземпляру класу MyClass1
функція spl_autoload_register
зчитує файл MyClass1.php
з каталогу src
. Ця реалізація передбачає, що кожен клас знаходиться в окремому файлі, який викликається за іменем класу або інтерфейсу.
У реальному застосуванні може виникнути багато неприємних ситуацій, які ускладнюють автозавантаження, наприклад:
При цьому нам не потрібно програмувати власне рішення для всього цього, а можна використати вже існуюче рішення, яке було розроблено.
Якщо ви використовуєте Composer, ви, ймовірно, також використовуєте його рідне автозавантаження. Це пов'язано з тим, що коли ви встановлюєте будь-який пакунок, Composer автоматично генерує "карту класів", яка є оглядом класів та їх фізичного розташування.
Потім на початку коду (зазвичай в index.php
) ви просто використовуєте:
require __DIR__ . '/vendor/autoload.php';
Однак автозавантаження генерується лише один раз при виклику команди composer dump
, тому необхідно перегенерувати автозавантаження при кожній зміні програми.
Для локальної розробки мені дуже подобається пакет nette/robot-loader
, який автоматично обходить структуру каталогів і кешує розташування класів. Тобто, якщо ми завантажуємо клас, то він спочатку дивиться в кеш і тільки якщо його немає, то автоматично переіндексує проект. Таким чином, програмісту взагалі не потрібно відслідковувати, де знаходиться той чи інший файл або клас, а просто програмувати.
Установка через Composer:
composer require nette/robot-loader
Базове пояснення функціоналу описано в самій документації:
Подібно до того, як робот Google сканує та індексує веб-сторінки, RobotLoader сканує всі PHP-скрипти та зазначає, які класи, інтерфейси та ознаки він знайшов у них. Потім він кешує результати своїх досліджень і використовує їх у наступному запиті. Тож вам потрібно лише вказати, які каталоги переглядати і де кешувати.
Після цього він надзвичайно простий у використанні:
$loader = new Nette\Loaders\RobotLoader;// додати каталоги, які RobotLoader повинен проіндексувати$loader->addDirectory(__DIR__ . '/app');$loader->addDirectory(__DIR__ . '/libs');// встановити кешування на диск в директорію 'temp'$loader->setTempDirectory(__DIR__ . '/temp');$loader->register(); // запустити RobotLoader
Параметр $loader->setAutoRefresh(true or false)
визначає, чи повинен RobotLoader переіндексувати файли при зустрічі з новим класом. На виробничих серверах це повинно бути вимкнено.
Все, тепер вам більше ніколи не доведеться мати справу з автозавантаженням.
При розробці реального проекту я використовую комбіноване рішення.
Як це працює в реальному житті, я завантажую встановлені пакунки через автозавантаження Composer (що дуже ефективно) і це вирішує проблему завантаження всіх класів в каталозі vendor
.
Потім код для конкретного проекту розміщується в директорії app
, де я обробляю автозавантаження лише декількох класів за допомогою RobotLoader. Важливо завжди тримати конкретне нанесення якомога меншим і якомога більше використовувати готові упаковки, це дуже сприяє повторному використанню.
Структура проекту виглядає наступним чином:
/appBootstrap.php <-- konfigurace/modelUserForm.php <-- projektové třídyRegisterFactory.php.../vendor... <-- knihovny/wwwindex.php <-- inicializace
Іноді може статися так, що не всі файли завжди будуть завантажуватися і у вас виникнуть проблеми.
Для налагодження рекомендую функцію 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: ... | uk