Skip to content

Instantly share code, notes, and snippets.

@Ocramius
Last active December 3, 2021 09:30
Show Gist options
  • Save Ocramius/7435899 to your computer and use it in GitHub Desktop.
Save Ocramius/7435899 to your computer and use it in GitHub Desktop.
`Zend\ServiceManager` examples
vendor
composer.lock
<?php
use Zend\ServiceManager\AbstractFactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\ServiceManager\ServiceManager;
require_once __DIR__ . '/vendor/autoload.php';
// abstract factories provide a way of mapping multiple services in one shot
class MyAbstractFactory implements AbstractFactoryInterface
{
public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName)
{
return true; // always able to instantiate the service
}
public function createServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName)
{
$object = new stdClass();
$object->name = $name;
$object->requestedName = $requestedName;
return $object;
}
}
class MySecondAbstractFactory implements AbstractFactoryInterface
{
public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName)
{
return 'tab' === $name;
}
public function createServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName)
{
return new stdClass();
}
}
$sm = new ServiceManager();
$sm->addAbstractFactory('MySecondAbstractFactory');
// abstract factories are stacked - careful with that!
$sm->addAbstractFactory('MyAbstractFactory', false);
$a = $sm->get('foo');
$b = $sm->get('Bar');
$c = $sm->get('BAZ');
$d = $sm->get('tab');
// $d is actually built by MySecondAbstractFactory
var_dump($a, $b, $c, $d);
{
"require": {
"zendframework/zend-servicemanager": "2.2.*"
}
}
<?php
use Zend\ServiceManager\ServiceManager;
use Zend\ServiceManager\Config;
die('Not a runnable example');
// this example shows the entire Zend\ServiceManager\Config structure
$sm = new ServiceManager(new Config([
'factories' => [
'serviceName' => 'factoryClassOrInstance',
],
'invokables' => [
'serviceName' => 'className',
],
'services' => [
'serviceName' => $instance,
],
'aliases' => [
'alias' => 'serviceName',
],
'abstract_factories' => [
'stack',
'of',
'abstractfactory',
'classes',
'or',
'instances',
],
'delegators' => [
'serviceName' => [
'stack',
'of',
'delegatorServiceName',
'or',
'className',
'or',
'instance'
]
],
'shared' => [
'serviceName' => false,
]
]));
<?php
use Zend\ServiceManager\DelegatorFactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\ServiceManager\ServiceManager;
require_once __DIR__ . '/vendor/autoload.php';
// Delegators are useful when we want to replace a service
// but still want to retain the original instance as well
// as its instantiation logic.
$sm = new ServiceManager();
$sm->setFactory('foo', function () {
$service = new \stdClass();
$service->first = 1;
$service->second = 2;
$service->third = 3;
return $service;
});
// this delegator replaces the passed in service with an `stdClass` containing
// the real service
class MyDelegator implements DelegatorFactoryInterface
{
public function createDelegatorWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName, $callback)
{
$obj = new stdClass();
$obj->service = $callback();
return $obj;
}
}
$sm->addDelegator('foo', 'MyDelegator');
var_dump($sm->get('foo'));
<?php
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\ServiceManager\ServiceManager;
require_once __DIR__ . '/vendor/autoload.php';
$sm = new ServiceManager();
// callable factory
$sm->setFactory('foo', function () { return new \stdClass(); });
$a = $sm->get('foo');
$b = $sm->get('foo');
$c = $sm->get('foo');
var_dump($a, $b, $c);
// factories can (and should!) be defined as classes
class MyFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceLocator)
{
return new stdClass();
}
}
$sm->setFactory('bar', 'MyFactory');
$d = $sm->get('bar');
$e = $sm->get('bar');
$f = $sm->get('bar');
var_dump($d, $e, $f);
<?php
use Zend\ServiceManager\ServiceManager;
require_once __DIR__ . '/vendor/autoload.php';
// initializers are called on every instantiated service, so they
// are useful in some cases, but expensive and "magic", since they
// may overwrite values set in factories
$sm = new ServiceManager();
// note: can also be an InitializerInterface instance
// also: initializers are also stacked - careful about their order!
$sm->addInitializer(function ($instance) {
$instance->initialized = true;
});
$sm->setInvokableClass('foo', 'stdClass', false);
$a = $sm->get('foo');
$b = $sm->get('foo');
$c = $sm->get('foo');
var_dump($a, $b, $c);
<?php
use Zend\ServiceManager\ServiceManager;
require_once __DIR__ . '/vendor/autoload.php';
$sm = new ServiceManager();
// invokables are shared by default
$sm->setInvokableClass('foo', 'stdClass');
$a = $sm->get('foo');
$b = $sm->get('foo');
$c = $sm->get('foo');
var_dump($a, $b, $c);
// marking the invokable as non-shared (works in general for services)
$sm->setInvokableClass('bar', 'stdClass', false);
$d = $sm->get('bar');
$e = $sm->get('bar');
$f = $sm->get('bar');
// new instances at every `get`:
var_dump($d, $e, $f);
<?php
use Zend\ServiceManager\AbstractPluginManager;
require_once __DIR__ . '/vendor/autoload.php';
// plugin managers are useful to map a set of services sharing a similar
// characteristic (in this case the interface).
// Zend\Mvc uses 7 or 8 different plugin managers to lazily initialize
// forms, form elements, view helpers, validators, controllers, etc...
interface Cookie {};
class ChocolateCookie implements Cookie {};
class ButterCookie implements Cookie {};
class Car {};
class CookieFactory extends AbstractPluginManager
{
public function validatePlugin($plugin)
{
if (! $plugin instanceof Cookie) {
throw new \Zend\ServiceManager\Exception\RuntimeException('Not a cookie!');
}
}
}
$sm = new CookieFactory();
$sm->setInvokableClass('chocolate', 'ChocolateCookie');
$sm->setInvokableClass('butter', 'ButterCookie');
$sm->setInvokableClass('not-a-cookie', 'Car');
var_dump($sm->get('chocolate'));
var_dump($sm->get('butter'));
// this will crash:
var_dump($sm->get('not-a-cookie'));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment