Zend Framework - диспетчер служб

Zend Framework включает мощную реализацию паттерна локатора сервисов, которая называется zend-servicemanager. Zend framework широко использует диспетчер служб для всех своих функций. Service Manager обеспечивает абстракцию высокого уровня для Zend Framework. Он также прекрасно интегрируется со всеми другими компонентами Zend Framework.

Установить Service Manager

Компонент Service Manager можно установить с помощью composer инструмент.

composer require zendframework/zend-servicemanager

пример

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

use Zend\ServiceManager\ServiceManager; 
use Zend\ServiceManager\Factory\InvokableFactory; 
use stdClass;  
$serviceManager = new ServiceManager([ 
   'factories' => [stdClass::class => InvokableFactory::class,], 
]);

Приведенный выше код регистрирует stdClass в систему с помощью Factoryвариант. Теперь мы можем получить экземпляр stdClass в любое время, используяget() метод диспетчера службы, как показано ниже.

use Zend\ServiceManager\ServiceManager;  
$object = $serviceManager->get(stdClass::class);

Метод get () совместно использует извлеченный объект, поэтому объект, возвращаемый путем многократного вызова метода get (), является одним и тем же экземпляром. Чтобы каждый раз получать новый экземпляр, диспетчер служб предоставляет другой метод, которым являетсяbuild() метод.

use Zend\ServiceManager\ServiceManager;  
$a = $serviceManager->build(stdClass::class); $b = $serviceManager->build(stdClass::class);

Регистрация сервис-менеджера

Диспетчер служб предоставляет набор методов для регистрации компонента. Некоторые из наиболее важных методов приведены ниже -

  • Заводской метод
  • Абстрактный фабричный метод
  • Метод инициализатора
  • Метод фабрики делегатора

Мы подробно обсудим каждый из них в следующих главах.

Заводской метод

Фабрика - это в основном любой вызываемый или любой класс, реализующий FactoryInterface (Zend \ ServiceManager \ Factory \ FactoryInterface).

FactoryInterface имеет единственный метод -

public function __invoke(ContainerInterface $container, $requestedName, array $options = null)

Детали аргументов FactoryInterface следующие:

  • container (ContainerInterface)- Это базовый интерфейс ServiceManager. Он дает возможность пользоваться другими услугами.

  • requestedName - Это название службы.

  • options - Предоставляет дополнительные возможности, необходимые для обслуживания.

Давайте создадим простой класс, реализующий FactoryInterface, и посмотрим, как зарегистрировать класс.

Тест класса - объект для извлечения

use stdClass;  
class Test { 
   public function __construct(stdClass $sc) { // use $sc 
   } 
}

В Test класс зависит от stdClass.

Класс TestFactory - класс для инициализации тестового объекта

class TestFactory implements FactoryInterface { 
   public function __invoke(ContainerInterface $container, $requestedName, 
      array $options = null) { $dep = $container->get(stdClass::class); return new Test($dep); 
   } 
}

TestFactory использует контейнер для получения stdClass, создает экземпляр класса Test и возвращает его.

Регистрация и использование Zend Framework

Давайте теперь поймем, как зарегистрироваться и использовать Zend Framework.

serviceManager $sc = new ServiceManager([ 'factories' => [stdClass::class => InvokableFactory::class, Test::class => TestFactory::class] ]); $test = $sc->get(Test::class);

Сервис-менеджер предоставляет специальный завод под названием InvokableFactoryдля получения любого класса, который не имеет зависимости. Например,stdClass можно настроить с помощью InvokableFactory, поскольку stdClass не зависит от других классов.

serviceManager $sc = new ServiceManager([ 
   'factories' => [stdClass::class => InvokableFactory::class] 
]);  
$stdC = $sc->get(stdClass::class);

Другой способ получить объект без реализации FactoryInterface или используя InvokableFactory использует встроенный метод, как показано ниже.

$serviceManager = new ServiceManager([ 'factories' => [ stdClass::class => InvokableFactory::class, Test::class => function(ContainerInterface $container, $requestedName) { $dep = $container->get(stdClass::class); return new Test($dep); 
      }, 
   ], 
]);

Абстрактный фабричный метод

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

AbstractFactoryInterface определяет метод проверки того, может ли объект быть создан в запрошенном экземпляре или нет. Если создание объекта возможно, он создаст объект, используя__invokemethod FactoryInterface и верните его.

Подпись AbstractFactoryInterface выглядит следующим образом:

public function canCreate(ContainerInterface $container, $requestedName)

Метод инициализатора

Метод инициализатора - это специальная опция для добавления дополнительной зависимости для уже созданных сервисов. Он реализуетInitializerInterface и подпись единственного доступного метода следующая -

public function(ContainerInterface $container, $instance)  
function(ContainerInterface $container, $instance) { 
   if (! $instance instanceof EventManagerAwareInterface) { return; } $instance->setEventManager($container->get(EventManager::class)); 
}

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

Фабричный метод делегатора

Zend Framework поддерживает шаблон делегаторов через DelegatorFactoryInterface. Его можно использовать для украшения сервиза.

Сигнатура этой функции следующая -

public function __invoke(ContainerInterface $container, 
   $name, callable $callback, array $options = null 
);

Здесь $callback отвечает за украшение экземпляра службы.

Ленивые службы

Ленивый сервис - это один из тех сервисов, которые не будут полностью инициализированы во время создания. На них просто ссылаются и инициализируются только тогда, когда это действительно необходимо. Один из лучших примеров - подключение к базе данных, которое может понадобиться не во всех местах. Это дорогой ресурс, и на его создание нужно много времени. Zend framework предоставляетLazyServiceFactory полученный из DelegatorFactoryInterface, который может производить ленивое обслуживание с помощью Delegator концепция и сторонний прокси-менеджер, который называется ocramius proxy manager.

Менеджер плагинов

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

Например, все службы проверки подпадают под ValidationPluginManager.

Вариант конфигурации

Диспетчер служб предоставляет несколько возможностей для расширения возможностей диспетчера служб. Они естьshared, shared_by_default и aliases. Как мы обсуждали ранее, полученные объекты по умолчанию распределяются между запрошенными объектами, и мы можем использоватьbuild()метод, чтобы получить отдельный объект. Мы также можем использоватьsharedопция, чтобы указать, к какой услуге следует предоставить общий доступ Вshared_by_default такой же, как shared функция, за исключением того, что она применяется ко всем услугам.

$serviceManager = new ServiceManager([ 
   'factories' => [ 
      stdClass::class => InvokableFactory::class 
   ], 
   'shared' => [ 
      stdClass::class => false // will not be shared 
   ], 
   'shared_by_default' => false, // will not be shared and applies to all service 
]);

В aliasesОпция может использоваться для предоставления альтернативного имени зарегистрированным службам. У этого есть как преимущества, так и недостатки. С положительной стороны, мы можем предоставить альтернативные короткие названия для услуги. Но, в то же время, название может вырываться из контекста и вносить ошибки.

aliases' => ['std' => stdClass::class, 'standard' => 'std']