Autoloading in Zend Framework (Автозагрузка классов в Zend Framework)

Original author: Zend
  • Translation
Вечер добрый уважаемое хабрасообщество. Представляю вашему вниманию свой перевод статьи из серии Learning Zend Framework.

Сразу хочу оговориться, что я не являюсь экспертом в области английского языка и не претендую на 100% правильный перевод, хотя в последнее время задался целью изучить его как можно лучше, ибо хочу свободно разговаривать, читать, писать.

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

Итак собственно перевод:


Введение



Автозагрузка (autoloading) представляет механизм который избавляет вас от надобности вручную отслеживать зависимости между файлами и классами в вашем PHP коде.

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

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

Кроме того использование автозагрузки может сэкономить много времени, так как вам больше
не нужно будет заботится о том, подключен ли уже какой либо файл или еще нет. Вам
не нужно проверять подключался ли файл ранее, и не получится ли так, что файл подключится еще
раз, отсюда отпадает необходимость использования require_once(); для подключения файлов.

Zend Framework рекомендует использование автозагрузки классов и предоставляет несколько средств для загрузки
сторонних классов, а так же загрузки классов внутри своего приложения. Данное руководство объясняет использование возможности автозагрузки классов с помощью Zend Framework, и поможет вам использовать данные возможности наиболее эффективно.

Цели и дизайн


Соглашения об именовании классов
.

Для того чтобы понять как использовать автозагрузку в Zned Framework, для начала необходимо понять
отношения между именами классов и именами файлов в данном фреймворке.

Zend Framework использует наименование классов принятое в PEAR, где между именами классов и именами файлов существует отношение 1:1. Проще говоря в ZF знак "_" в имени класса заменяется на "/", а в конце к имени класса прибавляется суффикс ".php". К примеру имя класса «Foo_Bar_Baz» указывает на реальный файл «Foo/Bar/Baz.php». Кроме того предполагается поиск файлов в переменной PHP include_path. Которая позволяет подключать файлы ища их в директориях которые указаны в данной конфируграционной опции.

Далее мы рекомендуем для всех ваших проектов использовать некий префикс. К примеру все имена
классов в Zend Framework начинаются с префикса «Zend_». Это позволяет избежать конфликтов имен
при использовании различных библиотек. Внутри Zend Framework мы называем такие префиксы пространствами
имен («namespaces»). Не путайте с пространствами имен языка PHP.

Такие правила и соглашения повсеместно используются в Zend Framework и при разработке мы рекомендуем вам
придерживаться данных правил.

Соглашения и дизайн автозагрузчика


Zend Framework реализаует автозагрузку с помощью класса Zend_Loader_Autoloader
который подчиняется следующим правилам и имеет следующие соглашения:

1. Обеспечивает соответсвие пространств имен. Если префикс класса отсутствует в зарегестрированных
внутри приложения пространствах имен возвращается FALSE. При помощи такой организации можно
передавать автозагрузку другим авто загрузчикам.
2. Позволяет включить режим fallback. При активации данного режима загрузчик будет пытаться
искать классы вне зависимости от «пространств имен» определенных для загрузчика.

3. Позволяет отключить вывод ошибок в случаях если загрузчик не смогу найти необходимый класс.
По умолчанию данная опция отключена. Однако при желании вы можете включить ее.

4. Позволяет создавать функции обратного вызова, например когда пользователь не хочет
использовать встроенный метод Zend_Loader::loadClass(). Но при этом хочет использовать
механизмы авто загрузчика Zend_Loader_Autoloader.

5. Позволяет выстраивать цепочки из различных загрузчиков. Таким образом можно подключить
свои функции для загрузки классов, которые например не попадают под соглашении о именовании
классов в Zend Framework. Вы можете использовать свой автозагрузчик и до и после станадартного
загрузчика Zend Framework.

Базовое использование загрузчика.



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

Проще всего подключить файл данного класса. И получить экземпляр загрузчика. Следует так же отметить
что загрузчик Zend Framework построен по паттерну singleton. Поэтому для получения объекта
используется метод getInstance().

  1.     require_once 'Zend/Loader/Autoloader.php';
  2.     Zend_Loader_Autoloader::getInstance();


По умолчанию загрузчик будет автоматически подключать все классы начинающиеся с префиксов
«Zend_» или «ZendX_», путь к которым указан в переменной include_path.

Что же делать, если вы захотите заставить загрузчика искать ваши классы которые имеют префикс отличный
от Zend_. Необходимо использовать метод registerNamespace(). Метод принимает в качестве параметра префикс или массив префиксов. После того как префиксы были добавлены при помощи данного метода,
загрузчик будет автоматически и искать классы с данным префиксом и подгружать их.

  1.     require_once 'Zend/Loader/Autoloader.php';
  2.     $loader = Zend_Loader_Autoloader::getInstance();
  3.     $loader->registerNamespace('Foo_');
  4.     $loader->registerNamespace(array('Foo_', 'Bar_'));


Коме того вы можете включить режим fallback. Это означает что загрузчик будет искать все классы не зависимо от префикса.

  1. $loader->setFallbackAutoloader(true);


Внимание
Не используйте режим fallback. Мы рекомендуем отказаться от данной опции, в проектах
Zend Framework, какой бы заманчивой она не казалась.


Zend_Loader_Autoloader использует метод Zend_Loader::loadClass(), который в свою очередь
исопльзует функцию include() для подключения файлов. При отсутствии файла, include()
вернет false. И PHP вернет предупреждение «WARNING ERROR».

Это может стать причиной некоторых проблем.
1. Если опция display_errors активна, предупреждение об ошибки будет направлено в поток вывода.
2. Если задан режим error_reporting отображающий вывод предупреждений, в ваш лог будут записываться
все предупреждения об ошибках подключения файлов.

Конечно вы можете отключить вывод ошибок внутри Zend_Loader_Autoloader даже если включена
опция display_errors. Однако данная опция позволит заглушить ошибки только в потоке вывода.
В лог ошибки будут писаться все равно, поэтому мы рекомендуем вам использовать префиксы к вашим
классам и регистрировать их в загрузчике.


На заметку:
Когда был написал данный мануал, вышел релиз PHP 5.3. Начиная с данной версии PHP
поддерживает пространства имен. Однако ZF разрабатывался до того как данная возможность
появилась в PHP, и мы договорились внутри фреймворка использовать пространства имен
назначая именам классов префиксы. К примеру префикс Zend_ у всех классов фреймворка.
Мы планируем включить поддержку пространств имен php в загрузчик начиная с 2-ой версии
фреймворка.


Если вы хотите использовать свои функции для автозагрузки файлов и классов с,
вы можете добавить их к загрузчику Zend_Loader_Autoloader при помощи методов pushAutoloader() и unshiftAutoloader(). Данные методы позволяют добавить ваш загрузчик до или после вызова загрузчика Zend Framework, и сформировать таким образом цепочку из разных загрузчиков.

Преимущества данного подхода заключаются в том, что:
1. Каждый из данных методов принимает второй необязательный параметр который является
префиксом классов для загрузки. Т.е. вы можете указать загрузчику Zend Framework,
что подключенный к цепочке загрузчик должен обрабатывать только классы с определенным префиксом.
2. У вас не будет проблем с управлением загрузкой, т.к. все методы цепочки имеют функции
обратного вызова. которыми лишен механизм spl_autoload_functions().

  1.     // Append function 'my_autoloader' to the stack,
  2.     // to manage classes with the prefix 'My_':
  3.     $loader->pushAutoloader('my_autoloader', 'My_');
  4.  
  5.     // Prepend static method Foo_Loader::autoload() to the stack,
  6.     // to manage classes with the prefix 'Foo_':
  7.     $loader->unshiftAutoloader(array('Foo_Loader', 'autoload'), 'Foo_');


Автозагрузка ресурсов.



При разработке реальных приложений иногда возникают ситуации, когда не все библиотеки приложения
попадают под рекомендации имен принятых в Zend Framework. Это значит что авто загрузчик не сможет
найти необходимые файлы.

Итак, если вы прочли раздел о соглашениях и дизайне загрузчика то вы можете догадаться,
что Zend Framework может решить данную проблему. Для этого существует класс Zend_Loader_Autoloader_Resource.
Ресурс подразумевает наличие имени и пути по которому будет происходить поиск необходимых классов
и файлов. В простейшем случае это выглядит примерно так:

  1.     $loader = new Zend_Application_Module_Autoloader(array(
  2.         'namespace' => 'Blog',
  3.         'basePath'  => APPLICATION_PATH . '/modules/blog',
  4.     ));


Прежде всего необходимо информировать загрузчика о типах ресурсов которые будут подключены.
Данные типы представляют из себя пары типа «ключ-значение».

Для примера возьмем следующее дерево каталогов:

  1.     path/to/some/resources/
  2.     |-- forms/
  3.     |   `-- Guestbook.php        // Foo_Form_Guestbook
  4.     |-- models/
  5.     |   |-- DbTable/
  6.     |   |   `-- Guestbook.php    // Foo_Model_DbTable_Guestbook
  7.     |   |-- Guestbook.php        // Foo_Model_Guestbook
  8.     |   `-- GuestbookMapper.php  // Foo_Model_GuestbookMapper


Для начала создадим ресурс:

  1.     $loader = new Zend_Loader_Autoloader_Resource(array(
  2.         'basePath'  => 'path/to/some/resources/',
  3.         'namespace' => 'Foo',
  4.     ));


После этого необходимо определить типы ресурсов. Метод Zend_Loader_Autoloader_Resourse::addResourceType()
принимает 3 агрумента. Первый аргумент это имя ресурса. Второй аргумент, директория в которой необходимо искать данный ресурс относительно коренной директории ресурса. Третий параметр, это префикс класса (или пространство имен).
В данном примере имеем 3 типа ресурса. первый form, находящийся в директории forms и имеющий префикс «Form_». Второй model, располагающийся в директории models и имеющий префикс Model_ и третий dbTable находящийся в соответствующих директориях.

  1.     $loader->addResourceType('form', 'forms', 'Form')
  2.            ->addResourceType('model', 'models', 'Model')
  3.            ->addResourceType('dbtable', 'models/DbTable', 'Model_DbTable');


После объявления мы можем загружать наши ресурсы используя следующие классы:

  1.     $form      = new Foo_Form_Guestbook();
  2.     $guestbook = new Foo_Model_Guestbook();


Заключение



Zend Framework поощряет применение автозагрузки классов (autoloading), и производит инициализацию
данного механизма в классе Zend_Application.
Надеемся что данное руководство дало вам необходимую информацию об использовании компонента Zend_Loader_Autoloader а так же помогло вам разобраться в его преимуществах, таких как подключение своих собственных автозагрузчиков классов (custom autoloaders) а так же авто загрузчиков ресурсов (resource autoloaders).

Для детального ознакомления с компонентами фреймворка: Zend_Loader_Autoloader и Zend_Loader_Autoloader_Resource вы можете прочесть соответсвующие разделы мануала. Zend_Loader_Autoloader и Zend_Loader_Autoloader_Resource.
Share post
AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 12

    0
    Выглядит информативно, добавил в избранное, почитаю на досуге. Спасибо за перевод!
      –2
      singletron => singleton
        0
        Исправил.
          0
          вот в личку сложно написать?
          ничего личного, просто заебывают совершенно бесполезные коменты

          А по поводу статьи, да, для быстрого деплоя это хорошо. Но ко всему с приставкой «авто» я отношусь настороженно
            0
            и таких сообщений в личку будут десятки. а так все желающие увидели что автору уже указали на ошибку и промолчали :)
          0
          Очень неплохая статья для новичков. Жаль мне в своё время такая не попалась. От себя добавлю ссылочку про подключение автозагрузки Doctrine к ZF:
          weierophinney.net/matthew/archives/220-Autoloading-Doctrine-and-Doctrine-entities-from-Zend-Framework.html
          0
          Есть еще вариант через application.ini, указав autoloadernamespaces
            0
            Разве можно отдельные ресурсы автолоадить через .ini? Насколько я знаю там только префиксы можно определять. Если ошибаюсь — было бы интересно узнать про автолоад ресурсов через .ini.
            0
            Объясните мне не грамотному, чем это нагромождение лучше 5ти строчек в __autoload()… OOP мания?
              0
              Это все про __autoload, только улучшеный.
              Например, по умолчанию App_Model_Class должен лежать здесь — app/model/class.php, но если он лежит здесь app/models/class.php — то добавив несколько строк, как написано в статье он будет автолоадится и из app/models/class.php.

              Все это конечно можно писать в __autoload, но в случае с коммандной разработкой у вас может не быть прямого доступа к нему.
                0
                Т.е. писать лишний код, который будет раздувать проект только из-за того, что кому-то захочется написать вместо models вместо model? Да и set_include_path еще не отменял никто.

            Only users with full accounts can post comments. Log in, please.