Подключение файлов в PHP через require, автозагрузка через SPL и использование composer
Любой проект содержит множество файлов, каждый из них может являться автономной единицей или использовать функционал кого-либо еще. Вот о взаимодействиях файлов и поговорим.
Допустим у нас есть проект со следующей файловой структурой:
- commands
- Command1.php
- Command2.php
- Command3.php
- CommandInterface.php
Пробежимся по содержимому директории commands. Каждый файл содержит в себе только один класс или интерфейс.
Command2 и Command3 отличаются от Command1 только названием класса.
Точкой входа является index.php и в зависомости от параметра action он создает экземпляр класса определенной команды и вызывает метод execute . Допустим он выгляди вот так:
'Command1', 'update' => 'Command2', 'delete' => 'Command3', ]; if (empty($_GET['action']) || !isset($actionsMap[$_GET['action']])) < throw new Exception('Bad request'); >$className = $actionsMap[$_GET['action']]; /** @var CommandInterface $command */ $command = new $className; echo $command->execute();Загвоздка в том, что файл index.php не знает где находятся классы Command1 , Command2 и Command3 . Попробуем это побороть.
Require
Так как мы знаем где что располагается, то прибегнем к самому простому варианту — добавим require наших файлов с командами в самый верх индексного:
Но этого оказывается недостаточно. Мы забыли про то, что команды реализуют CommandInterface , поэтому надо добавить еще его и обязательно перед подключением команд.
Итак, какие трудности мы встретили на нашем пути?
- PHP не знает где брать какой класс, мы должны ему подсунуть все необходимое
- необходимо держать в голове кто от кого зависит и соблюдать порядок require
Что еще может нам помешать в дальнейшем?
- вызов require одного и того же файла несколько раз породит ошибку
- добавление новых классов и зависимостей окончательно забьет голову тонной информации о связях
Решить первый вопрос поможет конструкция require_once, а вторую автозагрузчик SPL.
spl_autoload
Библиотека SPL содержит ряд функций для работы с автозагрузкой (spl_autoload_*), нам достаточно ограничиться одной — spl_autoload_register . Для этого создадим файл autoloader.php в корне проекта. В нем мы укажем правила соотношения названия класса с именем файла в котором он расположен. В нашем случае название класса и файла совпадают, поэтому получится достаточно просто:
// Все не ок. Мы не знаем, что это за файл return false; > // Регистрируем нашу функцию автозагрузки spl_autoload_register('commandsFolderAutoloader');А в index.php заменить все наши require на один require __DIR__ . DIRECTORY_SEPARATOR . ‘autoloader.php’; .
Проверяем. Все работает. Таким образом мы можем зарегистрировать несколько функций автозагрузки с произвольными правилами, но какие остались проблемы?
Основная проблема осталась одна — все приведенные решения являются нашими «велосипедами». Так как мы написали очередную реализацию давно решенной проблемы и не пользовались стандартами PSR-0, PSR-4. Поэтому предлагаю использовать автозагрузчик от composer .
Composer
Composer — это полноценный менеджер пакетов, который поддерживает два стандарта PSR-0 и PSR-4. Он отлично решит нашу проблему и даст задел на будущее при использовании сторонних пакетов.
Осталось только провести некоторые манипуляции:
- устанавливаем композер, если его нет
- выполняем composer init в корневой директории проекта
- добавляем в созданный composer.json секцию автозагрузки
< "name": "MothersEngineer/ComposerExample", "type": "project", "license": "MIT", "require": <>, "autoload": < "psr-0": < "": "commands" >> >
Вот и все. Наше «приложение» работает. Изначально этот вариант может показаться излишне сложным, но он окупится, когда мы начнем использовать сторонние компоненты.
Что почитать по теме
- Установка композера
- Автозагрузчик composer
- Стандарты автозагрузки PSR-0 и PSR-4
- Автоматическая загрузка классов в PHP
- 2017-11-16 08:46:53
