Zend Framework - Service Manager

O Zend Framework inclui uma implementação de padrão de localizador de serviço poderoso chamada zend-servicemanager. O framework Zend usa extensivamente o gerenciador de serviços para todas as suas funcionalidades. O Service Manager fornece uma abstração de alto nível para o Zend Framework. Ele também se integra perfeitamente com todos os outros componentes do Zend Framework.

Instale o Service Manager

O componente Service Manager pode ser instalado usando o composer ferramenta.

composer require zendframework/zend-servicemanager

Exemplo

Primeiro, todos os serviços precisam ser registrados no gerenciador de serviços. Uma vez que os serviços são registrados no sistema gerenciador do servidor, ele pode ser acessado a qualquer momento com o mínimo de esforço. O gerenciador de serviço oferece várias opções para registrar o serviço. Um exemplo simples é o seguinte -

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

O código acima registra o stdClass no sistema usando o Factoryopção. Agora, podemos obter uma instância de stdClass a qualquer momento usando oget() método do gerente de serviço, conforme mostrado abaixo.

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

O método get () compartilha o objeto recuperado e, portanto, o objeto retornado ao chamar o método get () várias vezes é uma única e mesma instância. Para obter uma instância diferente a cada vez, o gerente de serviço fornece outro método, que é obuild() método.

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

Registro de gerente de serviço

O gerenciador de serviço fornece um conjunto de métodos para registrar um componente. Alguns dos métodos mais importantes são os indicados abaixo -

  • Método de fábrica
  • Método de fábrica abstrato
  • Método inicializador
  • Método de fábrica de delegador

Discutiremos cada um deles em detalhes nos próximos capítulos.

Método de Fábrica

Uma fábrica é basicamente qualquer chamada ou qualquer classe que implemente o FactoryInterface (Zend \ ServiceManager \ Factory \ FactoryInterface).

O FactoryInterface tem um único método -

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

Os detalhes dos argumentos do FactoryInterface são os seguintes -

  • container (ContainerInterface)- É a interface base do ServiceManager. Ele fornece uma opção para obter outros serviços.

  • requestedName - É o nome do serviço.

  • options - Oferece opções adicionais necessárias para o serviço.

Vamos criar uma classe simples implementando o FactoryInterface e ver como registrar a classe.

Teste de classe - objeto a ser recuperado

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

o Test classe depende do stdClass.

Classe TestFactory - Classe para inicializar o objeto de teste

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

O TestFactory usa um contêiner para recuperar a stdClass, cria a instância da classe Test e a retorna.

Registro e uso do Zend Framework

Vamos agora entender como registrar e usar o Zend Framework.

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

O gerente de serviço fornece uma fábrica especial chamada InvokableFactorypara recuperar qualquer classe que não tenha dependência. Por exemplo, ostdClass pode ser configurado usando o InvokableFactory já que o stdClass não depende de nenhuma outra classe.

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

Outra maneira de recuperar um objeto sem implementar o FactoryInterface ou usando o InvokableFactory está usando o método embutido conforme fornecido abaixo.

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

Método de Fábrica Abstrato

Às vezes, podemos precisar criar objetos, que conhecemos apenas em tempo de execução. Esta situação pode ser tratada usando oAbstractFactoryInterface, que é derivado de FactoryInterface.

O AbstractFactoryInterface define um método para verificar se o objeto pode ser criado na instância solicitada ou não. Se a criação do objeto for possível, ele criará o objeto usando o__invokemethod do FactoryInterface e devolvê-lo.

A assinatura de AbstractFactoryInterface é a seguinte -

public function canCreate(ContainerInterface $container, $requestedName)

Método inicializador

O Método Initializer é uma opção especial para injetar dependência adicional para serviços já criados. Ele implementa oInitializerInterface e a assinatura do único método disponível é a seguinte -

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

No exemplo acima, o método verifica se a instância é do tipo EventManagerAwareInterface. Se for do tipoEventManagerAwareInterface, ele define o objeto gerenciador de eventos, caso contrário, não. Como o método pode ou não definir a dependência, ele não é confiável e produz muitos problemas de tempo de execução.

Método Delegator Factory

Zend Framework suporta o padrão de delegadores por meio de DelegatorFactoryInterface. Pode ser usado para decorar o serviço.

A assinatura desta função é a seguinte -

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

Aqui o $callback é responsável por decorar a instância do serviço.

Serviços preguiçosos

O serviço lento é um daqueles serviços que não serão totalmente inicializados no momento da criação. Eles são apenas referenciados e inicializados apenas quando realmente necessário. Um dos melhores exemplos é a conexão com o banco de dados, que pode não ser necessária em todos os lugares. É um recurso caro, além de ter um processo demorado para ser criado. Zend framework forneceLazyServiceFactory derivado do DelegatorFactoryInterface, que pode produzir serviço preguiçoso com a ajuda do Delegator conceito e um gerenciador de proxy de terceiros, que é chamado de ocramius proxy manager.

Gerenciador de Plugins

O Plugin Manager estende o gerenciador de serviços e fornece funcionalidades adicionais, como validação de instância. Zend Framework usa extensivamente o gerenciador de plugins.

Por exemplo, todos os serviços de validação vêm sob o ValidationPluginManager.

Opção de Configuração

O gerenciador de serviços fornece algumas opções para estender o recurso de um gerenciador de serviços. Eles sãoshared, shared_by_default e aliases. Como discutimos anteriormente, os objetos recuperados são compartilhados entre os objetos solicitados por padrão e podemos usar obuild()método para obter um objeto distinto. Também podemos usar osharedopção para especificar qual serviço a ser compartilhado. oshared_by_default é o mesmo que o shared recurso, exceto que se aplica a todos os serviços.

$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 
]);

o aliasesA opção pode ser usada para fornecer um nome alternativo aos serviços registrados. Isso tem vantagens e desvantagens. Do lado positivo, podemos fornecer nomes curtos alternativos para um serviço. Mas, ao mesmo tempo, o nome pode ficar fora de contexto e introduzir bugs.

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