Разрабатывая более-менее серьёзное web приложение с использованием OOP, очень часто приходится подключать классы используя инструкции require
, require_once
, include
, include_once
. При этом, как правило, каждый скрипт начинается из длинного списка подключаемых классов. Безусловно это проблема. Что если, например, изменится путь к какому то классу? В таком случае придется пройтись по всем файлам в котором используется этот класс и внести соответствующие изменения. К счастью для нас, разработчиков, предусмотрено решение этой проблемы.
В этой статье я очень подробно опишу процесс автозагрузки с практической точки зрения.
Немного истории
Давайте вспомним как мы делали в самом начале нашего пути изучения PHP, как мы только начинали использовать классы:
Файл index.php
<?php
require_once 'src/User.php'
$user = new User();
Как то так! При этом, мы подразумевали, что папка с нашими классами (src) находится в том же каталоге что и файл index.php. Это очень простой и бездумный вариант реализации, но очень трудно поддерживаемый в дальнейшем.
Функция __autoload()
Начиная с версии PHP 5, появился механизм автозагрузки классов и функция __autoload(), которая вызывается каждый раз, когда создается объект неизвестного класса. Единственное что оставалось разработчику, так это реализовать ее, и больше не было необходимости писать require. Вот как это выглядит на практике:
Файл index.php
<?php
function __autoload($class) {
require_once "src/$class.php";
}
// далее можно просто создавать объекты
$user = new User('Victor');
Следует заметить, что на сегодняшний день, функция __autoload() считается устаревшей и её использование не рекомендуется. Вместо неё, начиная с версии PHP 5.1.2 появился ряд методом, которые позволяют управлять процессом автозагрузки более гибко. Любопытному читателю я рекомендую почитать пост на хабре, в котором подробно описываются все эти методы и наводятся примеры их использования.
Автозагрузка классов из пространств имен
Быть может устаревший метод __autoload() Вам придется очень даже по душе (по своей простоте). Тем не менее, предлагаю пойти дальше и воспользоватся более продвинутыми возможностями версии PHP 5.3 — пространствами имен.
Автозагрузка классов из пространств имен подразумевает четко определенную структуру каталогов. К примеру, вот такая структура:
Здесь у нас объявлено два класса User
и UserRepository
. Описывая эти классы, мы должны указать пространство имен с помощью ключевого слова namespace
.
Обязательно нужно учитывать регистр символов в названиях пространств имен. Названия пространств имен и названия папок в файловой структуре должны совпадать.
В этом, конкретном случае, классы выглядят так:
Файл User.php
<?php
namespace Project\Entity;
class User implements \JsonSerializable {
private $id;
...
Файл UserRepository.php
<?php
namespace Project\Repository;
use Project\Entity\User;
class UserRepository {
protected $connect;
...
public function all(){
$user = new User();
}
Теперь, давайте посмотрим, что представляет из себя класс 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;
}
}
Принцип действия приведенного автозагружчика следующий:
- Сперва мы регистрируем пространство имен. Для этой цели используется метод
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());
В приведенном примере, мы зарегистрировали пространство имен Project
. Путь к папке с классами указываем относительно файла index.php
.
Это весь код, который необходимо написать чтобы автоматически подгружался любой класс из пространства имен Project
. Теперь мы можем создавать необходимые классы из любого файла приложения не используя инструкции типа include
, как показано в листинге 4, например.
При создании поста использовались такие ресурсы:
0 коммент.:
Отправить комментарий