Автозагрузка классов
lang_of_article_differ
want_proper_trans
Подключение других файлов в вашем сценарии
Когда вы пишете программу, которая состоит из более чем одного файла вам необходимо include
или require
файлы в другой с помощью
include 'filename.php';
require 'another.php';
Если вы используете кучу классов в вашем приложении вам нужно чтобы все они были проинклюжены в файл в котором вы их используете, это логично. Когда классов много, нужно писать кучу ненужного кода вверху сценария который портит вид вашего кода
Еще одним минусом явного включения файла в ваш сценарий есть то, что интерпретатору языка прийдется обработать включенные файлы и потратить на это время, даже если на самом деле вы не использовали классы которые находятся в тех файлах
<?php
include_once 'some/library.php'; // SomeLibrary class
if ($userLogged) {
$lib = new SomeLibrary();
// do some stuff
} else {
redirect_to('/');
}
В этом сценарии файл some/library.php
будет всегда анализироваться PHP и есть оперативную память и процессорное время, даже если пользователь не вошел в систему и перенаправляется на главную страницу сайта.
Таким образом, используя явное включение файлов не всегда является оптимальным решением. Конечно, вы можете включить вашу библиотеку только в том случае если пользователь залоглен на сайте:
<?php
if ($userLogged) {
include_once 'some/library.php'; // SomeLibrary class
$lib = new SomeLibrary();
// do some stuff
} else {
redirect_to('/');
}
Автоматическая загрузка недостающих файлов
Ручная загрузка зависимых файлов это хорошо, конечно, но это не всегда выглядит елегантно, согласитесь. На самом деле, php
имеет способность включать файлы автоматически: есть магическая функция которая вызываеться когда клас, используемый в скрипте не был найден в текущей области видимости. Это делается с помощью spl_autoload_register
:
spl_autoload_register(function ($class) {
// this function would be called when php would not find some $class
});
Вы должны установить функцию автозагрузки в начале вашего приложения и забыть о включении файлов после этого момента. Spl_autoload_register
принимает один параметр - функцию, которая должна вызываться, когда какой-то класс не найден. Ее параметр $class
будет иметь значение имя класса (включая пространство имен) который не был найден:
"\Catchmetech\AutoloadingLesson\ExampleController"
Если вы будете правильно генерировать имена для классов в системе и размещать их в нужных папках, то функция автозагрузки классов вам здорово поможет в дальнейшем.
Лучшая практика ( PSR
) говорит, что пространство имен должно соответствовать папкам и каждый класс должен быть в отдельном файле. Так, класс в приведенном выше примере должен находиться в папке Catchmetech\AutoloadingLesson
и должен быть назван ExampleController.php
. Конечно, каждый класс должен использовать пространство имен, как я уже упоминал в предыдущих уроках :)
Итак, как определить, какой файл я должен включить в моей функции автозагрузки? С помощью str_replace
заменим nemaspace разделители $class
с правильным для нашей операционной системы DIRECTORY_SEPARATOR
, добавим расширение файла и вуаля:
$fileName = str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php';
Хорошо, у нас есть путь к файлу, но он относительный, так как мы использовали неймспейс класса для этого дела. Мы должны добавить к этому пути префикс $baseDir
который должен соответствовать абсолютному пути к каталогу, где лежит наше приложение. Если вы правильно назвали классы и файлы - все будет работать
$baseDir = __DIR__.'/';
$fileName = $baseDir.$fileName;
Кроме того, мы можем проверить, есть ли файл, который мы ищем действительно существует в файловой системе посредством is_file
, и если нет - выкидаем иксепшн:
spl_autoload_register(function ($class) {
$base_dir = __DIR__.'/';
$file = $base_dir . str_replace('\\',DIRECTORY_SEPARATOR, $class) . '.php';
if (file_exists($file)) {
require $file;
} else {
throw new \Exception ('can\'t include '.$file.PHP_EOL.' when trying to load `'.$class.'`');
}
});
Вот и все, мы сделали автоматический загрузчик классов! Поместите код в верхней части загрузочного файла вашего приложения и забудьте о кучи include
в файлах!