Это просто фреймворк, или этот фреймворк олицетворяет собой гордость PHP-сообщества — его трудолюбивых разработчиков, так сказать, ключевой ингредиент? С россыпью конфигов… Предмет любви нашего ЯП, обладающий хорошим MVC, благодаря чему Zend Framework — самый лучший фреймворк на PHP.


Здесь вы не найдёте ответа на этот вопрос, зато узнаете про ServiceManager и ModuleManager.


Бегите, глупцы!


Предупреждение


  1. Данный материал основан на том, что я искал по Zend Framework 2, кое-где фигурируют даже упоминания по версии 1.*. Не думаю, что это станет проблемой при сопоставлении с другими версиями, так как рассматриваются фундаментальные моменты и вряд ли они глобально изменятся.
  2. В рассуждениях и переводах (а также в пункте 1) могут оказаться грубые ошибки, как мои, так и первоисточников. На всё будут даны ссылки, а собственное творчество будет с примечанием [моё].
  3. Ориентировано на тех, кто погуглил и, как я, запутался. Тут не будет разворачивания блогов, пояснений и интерактива. Но будет две картинки и кошечка.

Содержание


  • Термины
  • Устройство фреймворка
    • Общая структура и связи
    • Плагины
  • Визуализация
    • Связи
    • Схематичное представление
  • От автора
    • Полезные ссылки
  • Бонус

Термины


Источник, немного [моё].


  • Приложение — конечный продукт, сайт;
  • Модуль — функционально завершенный "блок" приложения, код которого может состоять из моделей, представлений, контроллеров. Модуль расширяет функциональные возможности веб-приложения и может функционировать лишь "внутри" него; Модули регистрируются в 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


Первичный обзор



Подробный разбор



ServiceManager


Quick start



Подробный разбор



ModuleManager


Документация



Надеюсь, краткий экскурс не слишком затянулся и был полезен. Разумеется, принимаются правки, предложения, критика и другие дозволенные правилами Хабра и действующими законодательствами РФ действия с вашей стороны.




Бонус, который мы заслужили:


Кошечка


(=^???^=)

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