18
ZF2 Service Manager by Bo Andersen

ZF2 Service Manager

Embed Size (px)

Citation preview

Page 1: ZF2 Service Manager

ZF2 Service Managerby Bo Andersen

Page 2: ZF2 Service Manager

What is the service manager all about?Implements the service locator design pattern

A central registry from which services (less formally, objects) are retrieved

Services are retrieved by a key

Keys must be unique across all modules; services are stored within an array in Zend\ServiceManager\ServiceManager

Lazily instantiates services when they are needed

When retrieving an object, one does not need to worry about instantiating it

Therefore, an object’s dependencies have already been resolved when the object is retrieved

More than a key-value registry as Zend_Registry in ZF1

Page 3: ZF2 Service Manager

A small disclaimer...Usually configured in a configuration file within each module

The module manager automatically merges these configuration files

The configuration files contain a PHP array

In this presentation, an imperative approach is used instead

That is, instead of large arrays, an object-oriented approach is used instead

This keeps everything more intuitive and easy to understand while discussing the theory

This is not the most common approach - don’t worry, we will work with the normal approach throughout the rest of the course!

Furthermore, to keep things simple, we will not include namespaces in the service keys in this presentation

Page 4: ZF2 Service Manager

Walkthrough of the service types

Page 5: ZF2 Service Manager

InvokablesA string that contains a fully qualified class name (i.e. including the

namespace)

When requesting an invokable, the service manager instantiates the class and returns the object

Adding an invokable to the service manager

$serviceManager->setInvokableClass('userService', 'User\Service\UserService');

Page 6: ZF2 Service Manager

Example: Retrieving an invokableWhen retrieving services, one does not need to know its type

An invokable is retrieved just like any other type of service

Retrieving a service

$userService = $serviceManager->get('userService');

Internally within the service manager

// $className contains 'User\Service\UserService'

return new $className();

Page 7: ZF2 Service Manager

FactoriesUsed to perform any setup or dependency injection for the requested

object

Either a PHP callable, an object or a fully qualified class name

If an object or class name, Zend\ServiceManager\FactoryInterface must be implemented (defines a createService method, which is invoked by the service manager)

In all cases, the object that is to be fetched should be returned

Factories are mostly used if the fetched object has dependencies that need to be resolved

Page 8: ZF2 Service Manager

Example: Adding & retrieving a factory$serviceManager->setFactory('userService', function($serviceManager) {

$logger = $serviceManager->get('My\Logger');

return new \User\Service\UserService($logger);

});

Fetching the service remains the same

$userService = $serviceManager->get('userService');

Page 9: ZF2 Service Manager

Abstract FactoriesEssentially a fallback in case a non-existing service is requested from

the service manager

The attached abstract factories will be queried to see if one of them can return the requested service

Two possible approaches; a string representing a fully qualified class name or an object

Zend\ServiceManager\AbstractFactoryInterface must be implemented

This interface defines two methods: canCreateServiceWithName and createServiceWithName

Page 10: ZF2 Service Manager

Abstract Factories (continued)public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName);

Determines whether or not the abstract factory can create a service with the provided name (returns boolean)

public function createServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName);

Responsible for creating a service with a given name and returning it. Invoked if canCreateServiceWithName returns TRUE

Page 11: ZF2 Service Manager

InitializersA block of code to be executed when a service is retrieved from the

service manager

Can be either a PHP callable, object or string containing a fully qualified class name

If an object or string is used, then the class must implement Zend\ServiceManager\InitializerInterface

The newly created instance is passed and it can thus be manipulated

Can sometimes replace factories

E.g. instead of injecting a database adapter into all repositories, a single initializer can accomplish this

Every service retrieved from the service manager will trigger all of the initializers

Only add an initializer for services that are frequently retrieved, because performance is affected

Page 12: ZF2 Service Manager

Example: Adding an initializerInject a database adapter into all services that implement AdapterAwareInterface

$serviceManager->addInitializer(function($instance, $serviceManager) {

if ($instance instanceof Zend\Db\Adapter\AdapterAwareInterface) {

$instance->setDbAdapter($serviceManager->get('Zend\Db\Adapter\Adapter'));

}

});

Page 13: ZF2 Service Manager

AliasesAn alias points from one service to another

When a service with an aliased name is requested, a different name should be used instead

For instance, if a service A is an alias for a service B, then a request for service A would actually return service B

Aliases can be of invokables, factories or other aliases (and hence they can be recursive)

This means that a service A can be an alias for service B, which in turn can be an alias for service C, and so on. In this scenario, requesting service A from the service manager would return service C

Page 14: ZF2 Service Manager

Aliases (continued)Aliases provide a lot of flexibility, particularly because of ZF2’s

modular structure

An application may be using Zend\Db\Adapter\Adapter for database connectivity

A module can refer directly to this key in the service manager

If for some reason this is no longer the case, then a lot of references would have to be updated

If an alias was used instead, one could do like in the below example

$serviceManager->setAlias('user_db_adapter', 'Zend\Db\Adapter\Adapter');

$dbAdapter = $serviceManager->get('user_db_adapter');

Page 15: ZF2 Service Manager

Shared ServicesServices registered with a service manager can be either shared or

not shared

In this context, the term shared refers to whether or not a new instance of a service is created on every request

If a service is shared, then an arbitrary number of requests for a given service will return the exact same object instance. Otherwise, a new instance will be created on every request

Services are shared by default

Page 16: ZF2 Service Manager

Example 1: Shared serviceDemonstrating the service manager’s default behavior$userService1 = $serviceManager->get('User\Service\UserService');

$userService2 = $serviceManager->get('User\Service\UserService');

The following line outputs: bool(true)

var_dump((spl_object_hash($userService1) === spl_object_hash($userService2)));

Page 17: ZF2 Service Manager

Example 2: Declaring service as not sharedOverriding the service manager’s default behavior

$serviceManager->setShared('User\Service\UserService', false);

$userService3 = $serviceManager->get('User\Service\UserService');

The following line outputs: bool(false)

var_dump((spl_object_hash($userService2) === spl_object_hash($userService3)));

Page 18: ZF2 Service Manager

that’s allThis presentation is part of my Zend Framework 2 online course.

Get 50% discount by navigating to the below URL!

https://www.udemy.com/zend-framework-2-from-beginner-to-professional/?couponCode=SS50