Это просто фреймворк, или этот фреймворк олицетворяет собой гордость PHP-сообщества — его трудолюбивых разработчиков, так сказать, ключевой ингредиент? С россыпью конфигов… Предмет любви нашего ЯП, обладающий хорошим MVC, благодаря чему Zend Framework — самый лучший фреймворк на PHP.
Здесь вы не найдёте ответа на этот вопрос, зато узнаете про ServiceManager и ModuleManager.
Предупреждение
- Данный материал основан на том, что я искал по Zend Framework 2, кое-где фигурируют даже упоминания по версии 1.*. Не думаю, что это станет проблемой при сопоставлении с другими версиями, так как рассматриваются фундаментальные моменты и вряд ли они глобально изменятся.
- В рассуждениях и переводах (а также в пункте 1) могут оказаться грубые ошибки, как мои, так и первоисточников. На всё будут даны ссылки, а собственное творчество будет с примечанием [моё].
- Ориентировано на тех, кто погуглил и, как я, запутался. Тут не будет разворачивания блогов, пояснений и интерактива. Но будет две картинки и кошечка.
Содержание
- Термины
- Устройство фреймворка
- Общая структура и связи
- Плагины
- Визуализация
- Связи
- Схематичное представление
- От автора
- Полезные ссылки
- Бонус
Термины
Источник, немного [моё].
- Приложение — конечный продукт, сайт;
- Модуль — функционально завершенный "блок" приложения, код которого может состоять из моделей, представлений, контроллеров. Модуль расширяет функциональные возможности веб-приложения и может функционировать лишь "внутри" него; Модули регистрируются в
application.config.php
в секцииmodules
- ModuleManager — контейнер для манипуляций модулями;
- Сервис — "механизм" в модуле, для манипуляций между моделями, контроллерами, видами, прочее; Сервисы регистрируются в
module.config.php
в секцииservice_manager
. - ServiceManager — контейнер для манипуляций сервисами.
- ControllerManager — работает с сервисами и фабриками для загрузки контроллеров (
\Zend\ServiceManager\AbstractFactoryInterface
или\Zend\ServiceManager\ServiceManager
). дока - EventManager — компонент, который агрегирует обработчики событий (Listener) для одного и более именованных событий (Event), а также инициирует обработку этих событий.
- Плагин — класс, который некоторым образом расширяет функциональность всех контроллеров.
Устройство фреймворка
Общая структура и связи
Когда создается Zend\Mvc\Application
, объект Zend\ServiceManager\ServiceManager
создается и настраивается через Zend\Mvc\Service\ServiceManagerConfig
. ServiceManagerConfig
получает конфигурацию из config/application.config.php
(или какой-либо другой конфиг приложения, который передаётся в Application
при его создании). Из всех сервисов и фабрик, представленных в пространстве имен Zend\Mvc\Service
, ServiceManagerConfig
является ответственным только за три: SharedEventManager
, EventManager
и ModuleManager
.
После этого Application
извлекает ModuleManager
. В этот момент ModuleManager
через ServiceManager
конфигурирует сервисы и фабрики, предоставляемые в Zend\Mvc\Service\ServiceListenerFactory
. Такой подход позволяет максимально упростить конфигурацию основного приложения и предоставить разработчику возможность конфигурировать различные части системы MVC из модулей, переопределяя любую конфигурацию по умолчанию в сервисах этих MVC.
ModuleManager
, выражен в Zend\Mvc\Service\ModuleManagerFactory
. Это, пожалуй, самая сложная фабрика в стеке MVC. ModuleManager
ожидает, что сервис ApplicationConfig
внедрён (Di) с ключами module_listener_options
и modules
.
Он создает экземпляр Zend\ModuleManager\Listener\DefaultListenerAggregate
, используя извлеченные module_listener_options
. Затем проверяет, существует ли сервис с именем ServiceListener
, если нет, то использует фабрику с именем Zend\Mvc\Service\ServiceListenerFactory
. В ServiceListener
будет добавлено множество сервисов слушателей, таких, как слушатели методов getServiceConfig
, getControllerConfig
, getControllerPluginConfig
, getViewHelperConfig
модуля.
Затем ModuleManager
извлекает сервис EventManager
и присоединяет вышеупомянутых слушателей. Он создает экземпляр Zend\ModuleManager\ModuleEvent
, установив параметр "ServiceManager" в объект менеджера сервисов. Наконец, он создает экземпляр Zend\ModuleManager\ModuleManager
и внедряет EventManager
и ModuleEvent
.
[моё] Тот случай, когда кодом понятнее:
<?php
namespace Zend\Mvc\Service;
use Zend\ModuleManager\Listener\DefaultListenerAggregate;
use Zend\ModuleManager\Listener\ListenerOptions;
use Zend\ModuleManager\ModuleEvent;
use Zend\ModuleManager\ModuleManager;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class ModuleManagerFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceLocator)
{
if (!$serviceLocator->has('ServiceListener')) {
$serviceLocator->setFactory('ServiceListener', 'Zend\Mvc\Service\ServiceListenerFactory');
}
$configuration = $serviceLocator->get('ApplicationConfig');
$listenerOptions = new ListenerOptions($configuration['module_listener_options']);
$defaultListeners = new DefaultListenerAggregate($listenerOptions);
$serviceListener = $serviceLocator->get('ServiceListener');
$serviceListener->addServiceManager(
$serviceLocator,
'service_manager',
'Zend\ModuleManager\Feature\ServiceProviderInterface',
'getServiceConfig'
); // то же самое для остальных методов модуля
$events = $serviceLocator->get('EventManager');
$events->attach($defaultListeners);
$events->attach($serviceListener);
$moduleEvent = new ModuleEvent;
$moduleEvent->setParam('ServiceManager', $serviceLocator);
$moduleManager = new ModuleManager($configuration['modules'], $events);
$moduleManager->setEvent($moduleEvent);
return $moduleManager;
}
}
Плагины
Архитектура контроллеров включает в себя систему плагинов, которая позволяет добавлять свой код, который будет вызываться при определенных событиях в процессе жизни контроллера. Фронт-контроллер использует брокер плагинов (plugin broker) в качестве реестра пользовательских плагинов, брокер плагинов также обеспечивает вызов методов событий в каждом плагине, зарегистрированном через фронт-контроллер.
Методы событий определены в абстрактном классе Zend_Controller_Plugin_Abstract
, от которого должны наследовать все пользовательские плагины
Визуализация
[моё]
- Читается сверху вниз, если не задано иное стрелками.
- Линии со стрелками указывают что во что входит.
- Тонкие линии без стрелок указывают что с чем связано.
- Толстые линии без стрелок указывают что чем управляет.
Связи
Схема
От автора
Внимательный читатель заметил, что статья начинается со ссылки на Тостер, где задан вопрос про различия ServiceManager и ModuleManager, и с них же начинается текст статьи. Совпадение? Не думаю. Дело в том, что Хабр стал первым местом, откуда я начал знакомство с основами фреймворка и путаницу внесла публикация, где воссоздавался блог из документации с комментариями автора статьи. Именно отсутствие описания ModuleManager толкнуло меня на неправильные рассуждения (что в ServiceManager регистрируются модули) и это привело к написанию данной статьи.
Полезные ссылки
Не хочу заниматься копипастой и выращивать 6 частей на одну тему, поэтому прикладываю список моих закладок по ZF с примечаниями:
Блог
В трёх статьях c Хабра
- https://habr.com/post/192522/
- Вольный перевод документации по разработке простого блога на ZendSkeletonApplication. Рассказывается о конфигах, ServiceManager (или ModuleManager, я так и не понял) и подключении сторонних библиотек.
Оригинал документации на блог
EventManager
Первичный обзор
- https://habr.com/post/131077/
- Быстрый обзор нового (на момент публикации) инструмента.
Подробный разбор
- http://zf2.com.ua/doc/50
- Документация из украинского сообщества по ZF.
ServiceManager
Quick start
- http://zf2.com.ua/doc/64, http://zf2.com.ua/doc/103
- Документация из украинского сообщества по ZF.
Подробный разбор
- https://habr.com/post/241471/
- Invokable, фабрики и другие непонятные штуки.
ModuleManager
Документация
- http://zf2.com.ua/doc/98
- Документация из украинского сообщества по ZF.
Надеюсь, краткий экскурс не слишком затянулся и был полезен. Разумеется, принимаются правки, предложения, критика и другие дозволенные правилами Хабра и действующими законодательствами РФ действия с вашей стороны.
Бонус, который мы заслужили:
Кошечка
(=^???^=)