Разрабатывая более-менее серьёзное web приложение с использованием OOP, очень часто приходится подключать классы используя инструкции require
, require_once
, include
, include_once
. При этом, как правило, каждый скрипт начинается из длинного списка подключаемых классов. Безусловно это проблема. Что если, например, изменится путь к какому то классу? В таком случае придется пройтись по всем файлам в котором используется этот класс и внести соответствующие изменения. К счастью для нас, разработчиков, предусмотрено решение этой проблемы.
В этой статье я очень подробно опишу процесс автозагрузки с практической точки зрения.
Немного истории
Давайте вспомним как мы делали в самом начале нашего пути изучения PHP, как мы только начинали использовать классы:
Файл index.php <?php require_once 'src/User.php' $user = new User();
Листинг 1.
Как то так! При этом, мы подразумевали, что папка с нашими классами (src) находится в том же каталоге что и файл index.php. Это очень простой и бездумный вариант реализации, но очень трудно поддерживаемый в дальнейшем.
Функция __autoload()
Начиная с версии PHP 5, появился механизм автозагрузки классов и функция __autoload(), которая вызывается каждый раз, когда создается объект неизвестного класса. Единственное что оставалось разработчику, так это реализовать ее, и больше не было необходимости писать require. Вот как это выглядит на практике:
Файл index.php <?php function __autoload($class) { require_once "src/$class.php"; } // далее можно просто создавать объекты $user = new User('Victor');
Листинг 2.
Следует заметить, что на сегодняшний день, функция __autoload() считается устаревшей и её использование не рекомендуется. Вместо неё, начиная с версии PHP 5.1.2 появился ряд методом, которые позволяют управлять процессом автозагрузки более гибко. Любопытному читателю я рекомендую почитать пост на хабре, в котором подробно описываются все эти методы и наводятся примеры их использования.
Автозагрузка классов из пространств имен
Быть может устаревший метод __autoload() Вам придется очень даже по душе (по своей простоте). Тем не менее, предлагаю пойти дальше и воспользоватся более продвинутыми возможностями версии PHP 5.3 — пространствами имен.
Автозагрузка классов из пространств имен подразумевает четко определенную структуру каталогов. К примеру, вот такая структура:
Здесь у нас объявлено два класса User
и UserRepository
. Описывая эти классы, мы должны указать пространство имен с помощью ключевого слова namespace
.
Обязательно нужно учитывать регистр символов в названиях пространств имен. Названия пространств имен и названия папок в файловой структуре должны совпадать.
В этом, конкретном случае, классы выглядят так:
Файл User.php <?php namespace Project\Entity; class User implements \JsonSerializable { private $id; ...
Листинг 3.
Файл UserRepository.php <?php namespace Project\Repository; use Project\Entity\User; class UserRepository { protected $connect; ... public function all(){ $user = new User(); }
Листинг 4.
Теперь, давайте посмотрим, что представляет из себя класс NamespaceAutoloader
. Вообще то ничего сложного:
Файл NamespaceAutoloader.php <?php class NamespaceAutoloader { protected $namespaceMap = array(); public function addNamespace($namespace, $rootDir){ if (is_dir($rootDir)){ $this->namespaceMap[$namespace] = $rootDir; return true; } return false; } public function register(){ spl_autoload_register(array($this, 'autoload')); } protected function autoload($class){ $pathParts = explode('\\', $class); if (is_array($pathParts)){ $namespace = array_shift($pathParts); if (!empty($this->namespaceMap[$namespace])){ $filePath = $this->namespaceMap[$namespace].'/'.implode('/', $pathParts).'.php'; require_once $filePath; return true; } } return false; } }
Листинг 5.
Принцип действия приведенного автозагружчика следующий:
- Сперва мы регистрируем пространство имен. Для этой цели используется метод
addNamespace()
. Для регистрации пространства имен, нужно передать два параметра: название пространсва имен и путь к папке в которой размещены классы. - Далее, вызовом метода
register()
, мы запускаем процесс автозагрузки.
В реальном примере, использование автозагружчика, выглядит таким образом:
Файл index.php <?php header('Content-type: application/json'); // Подключаем класс автозагружчика и создаем его экземпляр require_once 'NamespaceAutoloader.php'; $autoloader = new NamespaceAutoloader(); // Регистрируем пространство имен и запускаем автозагрузку $autoloader->addNamespace('Project', 'ServerSide'); $autoloader->register(); // Используем классы из пространства имен use Project\Repository\UserRepository; $userRepo = new UserRepository($connect); echo json_encode($userRepo->all());
Листинг 6.
В приведенном примере, мы зарегистрировали пространство имен Project
. Путь к папке с классами указываем относительно файла index.php
.
Это весь код, который необходимо написать чтобы автоматически подгружался любой класс из пространства имен Project
. Теперь мы можем создавать необходимые классы из любого файла приложения не используя инструкции типа include
, как показано в листинге 4, например.
При создании поста использовались такие ресурсы:
0 коммент.:
Отправить комментарий