Автоматическая подгрузка файлов с PHP-классами или избавляемся от include-ов

Stepler, 21.12.2008

В этой статье я хочу рассказать, как избавиться от include-ов файлов с PHP-классами и сделать их подгрузку полностью автоматической.

Этот метод актуален только для объектно-ориентированного стиля программирования, и будет работать в версии PHP 5.1.2 и выше.

Давайте рассмотрим пример. Имеем два файла:

Файл example.php:

<?php
class example {
  static  function call() {
    echo  'You call "' . __CLASS__ . '" class.';
  }
}
?>

Файл index.php:

<?php
  include 'example.php';
  example::call();
?>

Оба файла находятся в одной директории. В первом файле example.php объявлен класс example. Во втором файле мы подключаем example.php и вызываем метод call класса example. Метод call является статическим, поэтому нам не обязательно создавать экземпляр класса example для его вызова.

Результатом выполнения этого скрипта будет сообщение «You call "example" class.»

Для использования класса example, нам нужно было подгрузить соответствующий файл — example.php.

А теперь представьте, что классов у вас сотни, и вам нужно вручную каждый раз прописывать инклуды файлов с классами, чтобы все их использовать.

Давайте поступим проще! Напишем функцию, которая будет автоматически подгружать нужный нам файл с классом только тогда, когда мы начинаем использовать этот класс. То есть, если класс в ходе выполнения сценария не используется, то и подключать с ним файл нет необходимости.

Модифицируем предыдущий пример:

Файл autoload.php:

<?php
spl_autoload_register ('autoload');
function autoload ($className) {
  $fileName = $className . '.php';
  include  $fileName;
  }
?>

Файл example.php:

<?php
  class example {
  static  function call() {
  echo  'You call "' . __CLASS__ . '" class.';
  }
  }
?>

Файл index.php:

<?php
  include 'autoload.php';
  example::call();
?>

Мы добавили новый файл autoload.php и подгрузили его в index.php. Обратите внимание — мы все также вызываем example::call(), и вместо «Fatal error: Class "example" not found in …» получаем прежний результат — «You call "example" class.». Даже без ручной подгрузки файла example.php, класс example нашелся и его метод вызвался. Как так получилось?

PHP позволяет задать обработчик (функцию или метод класса) который будет вызываться всякий раз при обращении к классу, который еще не определен. Аргументом функции-обработчика является имя вызываемого класса. Обработчик мы определяем с помощью функции spl_autoload_register(). Если в качестве обработчика выступает функция, то аргументом spl_autoload_register() будет являться строка с именем функции (как в примере). Если же в качестве обработчика выступает метод класса, то аргументом spl_autoload_register() будет являться массив, первый элемент которого соответствует названию класса, а второй названию метода этого класса — spl_autoload_register(array('someoneClass', 'someoneMethod')). Метод-обработчик должен быть статическим.

В нашем примере, в качестве обработчика я использовал функцию autoload(). К имени вызываемого класса она добавляет расширение «.php» и пытается подгрузить файл <class>.php, где <class> — имя вызываемого класса.

Мы привели простой пример, чтобы вы поняли, как работает метод автоматической подгрузки файлов с классами, в следующий раз покажем реальное применение, где это может использоваться.

Подписаться на обновления блога

Вам понравился наш блог, хотите следить за обновлениями? Подпишитесь на RSS рассылку или рассылку по электронной почте. Так же вы можете следить за нами в Twitter.

Категории: PHP | Комментировать

Комментарии (16)

  1. Anton Shevchuk / 21.12.2008 в 20:52

    Только не стоит забывать, что такой способ более медленный чем привычный include (особенно когда автолоад будет не таким простым), и значит его не стоит использовать при разработки ядра CMS либо CMF, а вот при разработке конкретного приложения вполне сгодится…

  2. Stepler / 21.12.2008 в 22:54

    Только не стоит забывать, что такой способ более медленный чем привычный include.

    Полностью с Вами согласен. Однако любая автоматизация «кушает ресурсы» и в итоге замедляет работу скрипта, но она же и позволяет отвлечься от мелочей и переключится на более важные проблемы. Например при неграмотно составленном алгоритме работы скрипта, потери ресурсов могут быть просто колоссальными, и наоборот при оптимизации его работы, быстродействие будет увеличено в разы. На этом фоне автоинклуд просто капля в море и этим вполне можно пожертвовать.

  3. Alex Shepko / 22.12.2008 в 00:20

    Конечно автолоадеры должны быть простыми в реализации, однако если используются акселераторы кода, то об инклудах можно вообще не думать, главное всё правильно настроить и продумать архитектуру.

  4. Skaizer / 22.12.2008 в 01:52

    Не всегда акселераторы есть хорошо, и полагаться на них я бы не рекомендовал.

  5. adw0rd / 22.12.2008 в 17:27

    Да, добавить нечего… :-)
    Поправь «$calssName», думаю всётаки хотел написать «$className» :-)

  6. Stepler / 22.12.2008 в 17:42

    Спасибо, исправил :)

  7. Alex Shepko / 22.12.2008 в 23:48

    2Skaizer: тогда объясни в каких реальных ситуациях лучше не пользоваться акселераторами ?

  8. Skaizer / 23.12.2008 в 01:51

    Я не говорил, что пользоваться ими не стоит. Я говорил, что всегда полагаться на акселераторы не рекомендую. Не факт что на хостинге, где будет размещаться проект клиента имеется поддержка акселераторов.

    Ну а конкретно по вопросу — когда используется функция eval(), когда представление хранится в базе данных. В этих случаях оптимизация акселераторами невозможна. Конечно, ситуации довольно специфические :)

  9. Alex Shepko / 23.12.2008 в 11:08

    Сейчас многие хостеры имеют акселераторы, надо просто правильно выбирать. По поводу eval-a — возможно лучше пересмотреть архитектуру чем пренебрегать акселераторами и возможностью ускорить свой код как минимум на 7%

  10. Skaizer / 02.01.2009 в 16:17

    Мы пользуемся nichost.ru уже несколько лет, но там, к сожалению, акселераторы не установлены. Правда есть возможность установить их самому. Вот тут описан порядок установки APC. Я устанавливал eAccelerator, схема практически такая же.

    Кстати, вот интересны особенности различных акселераторов. Т.к. встав перед выбором — какой устанавливать, нужно опираться на что-то.

    Я поставил eAccelerator и WordPress стал потреблять в 4 раза меньше памяти при значении компрессии равной 9. Но может быть установив другой акселератор, можно получить лучший результат.

    Интересно было бы почитать про особенности настройки акселераторов, и сравнения их эффективности.

    Если у у вас имеются ссылочки по теме, выложите, пожалуйста.

  11. Caligula / 31.07.2010 в 19:46

    Получается, что у Вас имя класса и имя файла должны совпадать, в противном случае, если класс определен в произвольном файле, полезут ошибки. Даже если все правильно, то по сути все равно PHP делает столько include, сколько без прокладки autoload.php, т.е. производительность как минимум не увеличится.

  12. ссср / 04.10.2010 в 22:53

    Вы описали runtime загрузку библиотек. Если скрипты засунуты под FastCGI, то смысла в автозагрузчике особого не будет, придется классически инклудить все в начале выполнения скрипта.

  13. Валерий / 08.04.2015 в 13:57

    Спасибо, четко, ясно и понятно. При разборе кода мне пришлось столкнуться с этим вопросом и этот пост оказался ну очень кстати.

  14. Дмитрий / 27.04.2016 в 03:45

    Спасибо!, пример и разъяснение помогло, т.к. был небольшой стопор в похожей ситуации.

  15. Ronaldnug / 28.07.2016 в 01:15

    P050WbNuItpNXUs0NHJJ

  16. KethIndet / 09.02.2017 в 18:28

    u http://cialis24h.party how to buy cialis

Оставить комментарий

480×60
480×60