Автозагрузка классов
Вы уже знаете, что чтобы воспользоваться каким-нибудь классом, мы должны подключить его через require
. Когда в проекте очень много классов, то получается много подключений, которые очень неудобно писать и трудно контролировать.
Для решения такой проблемы в PHP была добавлена
автозагрузка
классов. Автозагрузка позволяет PHP автоматически загружать файл с классом при попытке обращения к этому классу в коде. Однако, просто так классы загружаться не будут - их необходимо разместить по папкам сайта специальным образом, следуя какому-нибудь соглашению об именах файлов и папок классов. Можно пользоваться встроенным в PHP соглашением, либо придумать свое и пользоваться им.
Стандартная функция
Давайте для начала разберем стандартное соглашение PHP. Это соглашение заключается в то, что если у нас есть некоторый файл с классом, то путь по папкам сайта к этому файлу должен совпадать с пространством имен файла, а имя файла должно совпадать с именем хранящегося в нем класса. При этом имена папок и файла должны быть в нижнем регистре.
Функция spl_autoload_register
пишется только один раз в начале файла. Затем можно создавать столько объектов разных классов, сколько угодно, главное, чтобы их имена следовали соглашениям. Функция spl_autoload_register
пишется только в начале того файла, который вызывается через адресную строку браузера. То есть, если какой-то класс вызывает внутри себя другой класс или наследует от кого-то, а сам класс вызывается в другом файле, то spl_autoload_register
нужно написать только в этом другом файле - в самом файле класса дублировать эту функцию не надо.
Посмотрим на примере. Пусть у нас есть следующий класс:
/core/admin/pagecontroller.php<?
namespace Core\Admin;
class PageController {}
По соглашению данный класс должен располагаться в папке /core/admin/
в файле pagecontroller.php
.
Давайте теперь в файле index.php
используем наш класс, не подключая его через require
, а используя автозагрузку. Для этого в начале файла, в котором вызываются классы, следует вызвать функцию spl_autoload_register
. Сделаем это:
index.php<?
// включаем автозагрузку
spl_autoload_register();
// спокойно создаем объект
$obj = new Core\Admin\PageController;
Своя функция
Часто автозагрузка по умолчанию может вас не устраивать по каким-нибудь причинам. В таком случае можно написать свою автозагрузку.
Для этого в функцию spl_autoload_register
нужно первым параметром передать написанную вами функцию-коллбэк. Эта функция будет вызываться, когда PHP будет обнаруживать обращение к незагруженному классу. В параметр этой функции будет попадать имя класса с пространством имен:
<?
spl_autoload_register(function($class) {
// в переменной $class будет имя класса с пространством имен
});
А обязанностью функции будет по имени класса выполнить загрузку этого класса через require
. То есть внутри этой функции мы должны прописать свое правило для загрузки классов, то есть свое соглашение имен.
Давайте напишем пример какой-нибудь своей автозагрузки. Пусть, например, мы говорим, что путь к файлу класса от корня сайта будет такой же, как и пространство имен, но с сохранением регистра символов.
То есть, если у нас есть класс Core\Admin\PageController
, то путь к нему должен быть Core/Admin/PageController.php
.
Как вы видите, для преобразования имени класса с его пространством нужно просто поменять обратные слеши на прямые, а к имени класса добавить .php
. Сделаем это:
<?
spl_autoload_register(function ($class) {
$filename = str_replace('\\', '/', $class) . '.php';
require($filename);
});
У нас, однако, получится относительный путь к файлу (относительно корня сайта). Лучше сделать абсолютный путь, вот так:
<?
spl_autoload_register(function ($class) {
$root = $_SERVER['DOCUMENT_ROOT'];
$filename = $root . '/' . str_replace('\\', '/', $class) . '.php';
require($filename);
});
Есть еще нюанс. В разных операционных системах путь по папкам может быть с прямым слешем или с обратным. Сделаем наш код независимым от операционной системы. Для этого вместо прямого слеша для разделения путей будем ставить константу DIRECTORY_SEPARATOR
, содержащую правильный слеш той операционной системы, в который сейчас запускается наш скрипт. В итоге получим следующий код:
<?
spl_autoload_register(function ($class) {
$root = $_SERVER['DOCUMENT_ROOT'];
$ds = DIRECTORY_SEPARATOR;
$filename = $root . $ds . str_replace('\\', $ds, $class) . '.php';
require($filename);
});