3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
10 namespace Zend\ServiceManager
;
14 class ServiceManager
implements ServiceLocatorInterface
20 const SCOPE_PARENT
= 'parent';
21 const SCOPE_CHILD
= 'child';
25 * Lookup for canonicalized names.
29 protected $canonicalNames = array();
34 protected $allowOverride = false;
39 protected $invokableClasses = array();
42 * @var string|callable|\Closure|FactoryInterface[]
44 protected $factories = array();
47 * @var AbstractFactoryInterface[]
49 protected $abstractFactories = array();
54 protected $delegators = array();
59 protected $pendingAbstractFactoryRequests = array();
64 protected $lastAbstractFactoryUsed = null;
69 protected $lastCanonicalNameUsed = null;
74 protected $shared = array();
77 * Registered services and cached values
81 protected $instances = array();
86 protected $aliases = array();
91 protected $initializers = array();
94 * @var ServiceManager[]
96 protected $peeringServiceManagers = array();
99 * Whether or not to share by default
103 protected $shareByDefault = true;
108 protected $retrieveFromPeeringManagerFirst = false;
111 * @var bool Track whether not to throw exceptions during create()
113 protected $throwExceptionInCreate = true;
116 * @var array map of characters to be replaced through strtr
118 protected $canonicalNamesReplacements = array('-' => '', '_' => '', ' ' => '', '\\' => '', '/' => '');
123 * @param ConfigInterface $config
125 public function __construct(ConfigInterface
$config = null)
128 $config->configureServiceManager($this);
135 * @param $allowOverride
136 * @return ServiceManager
138 public function setAllowOverride($allowOverride)
140 $this->allowOverride
= (bool) $allowOverride;
149 public function getAllowOverride()
151 return $this->allowOverride
;
155 * Set flag indicating whether services are shared by default
157 * @param bool $shareByDefault
158 * @return ServiceManager
159 * @throws Exception\RuntimeException if allowOverride is false
161 public function setShareByDefault($shareByDefault)
163 if ($this->allowOverride
=== false) {
164 throw new Exception\
RuntimeException(sprintf(
165 '%s: cannot alter default shared service setting; container is marked immutable (allow_override is false)',
166 get_class($this) . '::' . __FUNCTION__
169 $this->shareByDefault
= (bool) $shareByDefault;
174 * Are services shared by default?
178 public function shareByDefault()
180 return $this->shareByDefault
;
184 * Set throw exceptions in create
186 * @param bool $throwExceptionInCreate
187 * @return ServiceManager
189 public function setThrowExceptionInCreate($throwExceptionInCreate)
191 $this->throwExceptionInCreate
= $throwExceptionInCreate;
196 * Get throw exceptions in create
200 public function getThrowExceptionInCreate()
202 return $this->throwExceptionInCreate
;
206 * Set flag indicating whether to pull from peering manager before attempting creation
208 * @param bool $retrieveFromPeeringManagerFirst
209 * @return ServiceManager
211 public function setRetrieveFromPeeringManagerFirst($retrieveFromPeeringManagerFirst = true)
213 $this->retrieveFromPeeringManagerFirst
= (bool) $retrieveFromPeeringManagerFirst;
218 * Should we retrieve from the peering manager prior to attempting to create a service?
222 public function retrieveFromPeeringManagerFirst()
224 return $this->retrieveFromPeeringManagerFirst
;
228 * Set invokable class
230 * @param string $name
231 * @param string $invokableClass
232 * @param bool $shared
233 * @return ServiceManager
234 * @throws Exception\InvalidServiceNameException
236 public function setInvokableClass($name, $invokableClass, $shared = null)
238 $cName = $this->canonicalizeName($name);
240 if ($this->has(array($cName, $name), false)) {
241 if ($this->allowOverride
=== false) {
242 throw new Exception\
InvalidServiceNameException(sprintf(
243 'A service by the name or alias "%s" already exists and cannot be overridden; please use an alternate name',
247 $this->unregisterService($cName);
250 if ($shared === null) {
251 $shared = $this->shareByDefault
;
254 $this->invokableClasses
[$cName] = $invokableClass;
255 $this->shared
[$cName] = (bool) $shared;
263 * @param string $name
264 * @param string|FactoryInterface|callable $factory
265 * @param bool $shared
266 * @return ServiceManager
267 * @throws Exception\InvalidArgumentException
268 * @throws Exception\InvalidServiceNameException
270 public function setFactory($name, $factory, $shared = null)
272 $cName = $this->canonicalizeName($name);
274 if (!($factory instanceof FactoryInterface ||
is_string($factory) ||
is_callable($factory))) {
275 throw new Exception\
InvalidArgumentException(
276 'Provided abstract factory must be the class name of an abstract factory or an instance of an AbstractFactoryInterface.'
280 if ($this->has(array($cName, $name), false)) {
281 if ($this->allowOverride
=== false) {
282 throw new Exception\
InvalidServiceNameException(sprintf(
283 'A service by the name or alias "%s" already exists and cannot be overridden, please use an alternate name',
287 $this->unregisterService($cName);
290 if ($shared === null) {
291 $shared = $this->shareByDefault
;
294 $this->factories
[$cName] = $factory;
295 $this->shared
[$cName] = (bool) $shared;
301 * Add abstract factory
303 * @param AbstractFactoryInterface|string $factory
304 * @param bool $topOfStack
305 * @return ServiceManager
306 * @throws Exception\InvalidArgumentException if the abstract factory is invalid
308 public function addAbstractFactory($factory, $topOfStack = true)
310 if (!$factory instanceof AbstractFactoryInterface
&& is_string($factory)) {
311 $factory = new $factory();
314 if (!$factory instanceof AbstractFactoryInterface
) {
315 throw new Exception\
InvalidArgumentException(
316 'Provided abstract factory must be the class name of an abstract'
317 . ' factory or an instance of an AbstractFactoryInterface.'
322 array_unshift($this->abstractFactories
, $factory);
324 array_push($this->abstractFactories
, $factory);
330 * Sets the given service name as to be handled by a delegator factory
332 * @param string $serviceName name of the service being the delegate
333 * @param string $delegatorFactoryName name of the service being the delegator factory
335 * @return ServiceManager
337 public function addDelegator($serviceName, $delegatorFactoryName)
339 $cName = $this->canonicalizeName($serviceName);
341 if (!isset($this->delegators
[$cName])) {
342 $this->delegators
[$cName] = array();
345 $this->delegators
[$cName][] = $delegatorFactoryName;
353 * @param callable|InitializerInterface $initializer
354 * @param bool $topOfStack
355 * @return ServiceManager
356 * @throws Exception\InvalidArgumentException
358 public function addInitializer($initializer, $topOfStack = true)
360 if (!($initializer instanceof InitializerInterface ||
is_callable($initializer))) {
361 if (is_string($initializer)) {
362 $initializer = new $initializer;
365 if (!($initializer instanceof InitializerInterface ||
is_callable($initializer))) {
366 throw new Exception\
InvalidArgumentException('$initializer should be callable.');
371 array_unshift($this->initializers
, $initializer);
373 array_push($this->initializers
, $initializer);
379 * Register a service with the locator
381 * @param string $name
382 * @param mixed $service
383 * @return ServiceManager
384 * @throws Exception\InvalidServiceNameException
386 public function setService($name, $service)
388 $cName = $this->canonicalizeName($name);
390 if ($this->has($cName, false)) {
391 if ($this->allowOverride
=== false) {
392 throw new Exception\
InvalidServiceNameException(sprintf(
393 '%s: A service by the name "%s" or alias already exists and cannot be overridden, please use an alternate name.',
394 get_class($this) . '::' . __FUNCTION__
,
398 $this->unregisterService($cName);
401 $this->instances
[$cName] = $service;
407 * @param string $name
408 * @param bool $isShared
409 * @return ServiceManager
410 * @throws Exception\ServiceNotFoundException
412 public function setShared($name, $isShared)
414 $cName = $this->canonicalizeName($name);
417 !isset($this->invokableClasses
[$cName])
418 && !isset($this->factories
[$cName])
419 && !$this->canCreateFromAbstractFactory($cName, $name)
421 throw new Exception\
ServiceNotFoundException(sprintf(
422 '%s: A service by the name "%s" was not found and could not be marked as shared',
423 get_class($this) . '::' . __FUNCTION__
,
428 $this->shared
[$cName] = (bool) $isShared;
433 * Resolve the alias for the given canonical name
435 * @param string $cName The canonical name to resolve
436 * @return string The resolved canonical name
438 protected function resolveAlias($cName)
442 while ($this->hasAlias($cName)) {
443 if (isset($stack[$cName])) {
444 throw new Exception\
CircularReferenceException(sprintf(
445 'Circular alias reference: %s -> %s',
446 implode(' -> ', $stack),
451 $stack[$cName] = $cName;
452 $cName = $this->aliases
[$cName];
459 * Retrieve a registered instance
461 * @param string $name
462 * @param bool $usePeeringServiceManagers
463 * @throws Exception\ServiceNotFoundException
464 * @return object|array
466 public function get($name, $usePeeringServiceManagers = true)
468 // inlined code from ServiceManager::canonicalizeName for performance
469 if (isset($this->canonicalNames
[$name])) {
470 $cName = $this->canonicalNames
[$name];
472 $cName = $this->canonicalizeName($name);
477 if ($this->hasAlias($cName)) {
479 $cName = $this->resolveAlias($cName);
484 if ($usePeeringServiceManagers && $this->retrieveFromPeeringManagerFirst
) {
485 $instance = $this->retrieveFromPeeringManager($name);
487 if (null !== $instance) {
492 if (isset($this->instances
[$cName])) {
493 return $this->instances
[$cName];
498 isset($this->invokableClasses
[$cName])
499 ||
isset($this->factories
[$cName])
500 ||
isset($this->aliases
[$cName])
501 ||
$this->canCreateFromAbstractFactory($cName, $name)
503 $instance = $this->create(array($cName, $name));
504 } elseif ($usePeeringServiceManagers && !$this->retrieveFromPeeringManagerFirst
) {
505 $instance = $this->retrieveFromPeeringManager($name);
509 // Still no instance? raise an exception
510 if ($instance === null) {
512 throw new Exception\
ServiceNotFoundException(sprintf(
513 'An alias "%s" was requested but no service could be found.',
518 throw new Exception\
ServiceNotFoundException(sprintf(
519 '%s was unable to fetch or create an instance for %s',
520 get_class($this) . '::' . __FUNCTION__
,
526 ($this->shareByDefault
&& !isset($this->shared
[$cName]))
527 ||
(isset($this->shared
[$cName]) && $this->shared
[$cName] === true)
529 $this->instances
[$cName] = $instance;
536 * Create an instance of the requested service
538 * @param string|array $name
540 * @return bool|object
542 public function create($name)
544 if (is_array($name)) {
545 list($cName, $rName) = $name;
549 // inlined code from ServiceManager::canonicalizeName for performance
550 if (isset($this->canonicalNames
[$rName])) {
551 $cName = $this->canonicalNames
[$name];
553 $cName = $this->canonicalizeName($name);
557 if (isset($this->delegators
[$cName])) {
558 return $this->createDelegatorFromFactory($cName, $rName);
561 return $this->doCreate($rName, $cName);
565 * Creates a callback that uses a delegator to create a service
567 * @param DelegatorFactoryInterface|callable $delegatorFactory the delegator factory
568 * @param string $rName requested service name
569 * @param string $cName canonical service name
570 * @param callable $creationCallback callback for instantiating the real service
574 private function createDelegatorCallback($delegatorFactory, $rName, $cName, $creationCallback)
576 $serviceManager = $this;
578 return function () use ($serviceManager, $delegatorFactory, $rName, $cName, $creationCallback) {
579 return $delegatorFactory instanceof DelegatorFactoryInterface
580 ?
$delegatorFactory->createDelegatorWithName($serviceManager, $cName, $rName, $creationCallback)
581 : $delegatorFactory($serviceManager, $cName, $rName, $creationCallback);
586 * Actually creates the service
588 * @param string $rName real service name
589 * @param string $cName canonicalized service name
591 * @return bool|mixed|null|object
592 * @throws Exception\ServiceNotFoundException
594 * @internal this method is internal because of PHP 5.3 compatibility - do not explicitly use it
596 public function doCreate($rName, $cName)
600 if (isset($this->factories
[$cName])) {
601 $instance = $this->createFromFactory($cName, $rName);
604 if ($instance === null && isset($this->invokableClasses
[$cName])) {
605 $instance = $this->createFromInvokable($cName, $rName);
608 if ($instance === null && $this->canCreateFromAbstractFactory($cName, $rName)) {
609 $instance = $this->createFromAbstractFactory($cName, $rName);
612 if ($instance === null && $this->throwExceptionInCreate
) {
613 throw new Exception\
ServiceNotFoundException(sprintf(
614 'No valid instance was found for %s%s',
616 ($rName ?
'(alias: ' . $rName . ')' : '')
620 // Do not call initializers if we do not have an instance
621 if ($instance === null) {
625 foreach ($this->initializers
as $initializer) {
626 if ($initializer instanceof InitializerInterface
) {
627 $initializer->initialize($instance, $this);
629 call_user_func($initializer, $instance, $this);
637 * Determine if we can create an instance.
639 * @param string|array $name
640 * @param bool $checkAbstractFactories
643 * @deprecated this method is being deprecated as of zendframework 2.2, and may be removed in future major versions
645 public function canCreate($name, $checkAbstractFactories = true)
647 if (is_array($name)) {
648 list($cName, $rName) = $name;
651 $cName = $this->canonicalizeName($rName);
655 isset($this->invokableClasses
[$cName])
656 ||
isset($this->factories
[$cName])
657 ||
isset($this->aliases
[$cName])
658 ||
isset($this->instances
[$cName])
659 ||
($checkAbstractFactories && $this->canCreateFromAbstractFactory($cName, $rName))
664 * @param string|array $name
665 * @param bool $checkAbstractFactories
666 * @param bool $usePeeringServiceManagers
669 public function has($name, $checkAbstractFactories = true, $usePeeringServiceManagers = true)
671 if (is_array($name)) {
672 list($cName, $rName) = $name;
676 // inlined code from ServiceManager::canonicalizeName for performance
677 if (isset($this->canonicalNames
[$rName])) {
678 $cName = $this->canonicalNames
[$name];
680 $cName = $this->canonicalizeName($name);
685 isset($this->invokableClasses
[$cName])
686 ||
isset($this->factories
[$cName])
687 ||
isset($this->aliases
[$cName])
688 ||
isset($this->instances
[$cName])
689 ||
($checkAbstractFactories && $this->canCreateFromAbstractFactory($cName, $name))
694 if ($usePeeringServiceManagers) {
695 foreach ($this->peeringServiceManagers
as $peeringServiceManager) {
696 if ($peeringServiceManager->has($rName)) {
706 * Determine if we can create an instance from an abstract factory.
708 * @param string $cName
709 * @param string $rName
712 public function canCreateFromAbstractFactory($cName, $rName)
714 // check abstract factories
715 foreach ($this->abstractFactories
as $abstractFactory) {
716 $factoryClass = get_class($abstractFactory);
719 isset($this->pendingAbstractFactoryRequests
[$factoryClass])
720 && $this->pendingAbstractFactoryRequests
[$factoryClass] == $rName
725 $objectHash = spl_object_hash($abstractFactory);
727 if ($this->lastAbstractFactoryUsed
=== $objectHash && $this->lastCanonicalNameUsed
=== $cName) {
728 $this->lastAbstractFactoryUsed
= $this->lastCanonicalNameUsed
= null;
732 $this->lastAbstractFactoryUsed
= $objectHash;
733 $this->lastCanonicalNameUsed
= $cName;
735 if ($abstractFactory->canCreateServiceWithName($this, $cName, $rName)) {
736 $this->lastAbstractFactoryUsed
= $this->lastCanonicalNameUsed
= null;
744 * Ensure the alias definition will not result in a circular reference
746 * @param string $alias
747 * @param string $nameOrAlias
748 * @throws Exception\CircularReferenceException
751 protected function checkForCircularAliasReference($alias, $nameOrAlias)
753 $aliases = $this->aliases
;
754 $aliases[$alias] = $nameOrAlias;
757 while (isset($aliases[$alias])) {
758 if (isset($stack[$alias])) {
759 throw new Exception\
CircularReferenceException(sprintf(
760 'The alias definition "%s" : "%s" results in a circular reference: "%s" -> "%s"',
763 implode('" -> "', $stack),
768 $stack[$alias] = $alias;
769 $alias = $aliases[$alias];
776 * @param string $alias
777 * @param string $nameOrAlias
778 * @return ServiceManager
779 * @throws Exception\ServiceNotFoundException
780 * @throws Exception\InvalidServiceNameException
782 public function setAlias($alias, $nameOrAlias)
784 if (!is_string($alias) ||
!is_string($nameOrAlias)) {
785 throw new Exception\
InvalidServiceNameException('Service or alias names must be strings.');
788 $cAlias = $this->canonicalizeName($alias);
789 $nameOrAlias = $this->canonicalizeName($nameOrAlias);
791 if ($alias == '' ||
$nameOrAlias == '') {
792 throw new Exception\
InvalidServiceNameException('Invalid service name alias');
795 if ($this->allowOverride
=== false && $this->has(array($cAlias, $alias), false)) {
796 throw new Exception\
InvalidServiceNameException(sprintf(
797 'An alias by the name "%s" or "%s" already exists',
803 if ($this->hasAlias($alias)) {
804 $this->checkForCircularAliasReference($cAlias, $nameOrAlias);
807 $this->aliases
[$cAlias] = $nameOrAlias;
812 * Determine if we have an alias
814 * @param string $alias
817 public function hasAlias($alias)
819 return isset($this->aliases
[$this->canonicalizeName($alias)]);
823 * Create scoped service manager
825 * @param string $peering
826 * @return ServiceManager
828 public function createScopedServiceManager($peering = self
::SCOPE_PARENT
)
830 $scopedServiceManager = new ServiceManager();
831 if ($peering == self
::SCOPE_PARENT
) {
832 $scopedServiceManager->peeringServiceManagers
[] = $this;
834 if ($peering == self
::SCOPE_CHILD
) {
835 $this->peeringServiceManagers
[] = $scopedServiceManager;
837 return $scopedServiceManager;
841 * Add a peering relationship
843 * @param ServiceManager $manager
844 * @param string $peering
845 * @return ServiceManager
847 public function addPeeringServiceManager(ServiceManager
$manager, $peering = self
::SCOPE_PARENT
)
849 if ($peering == self
::SCOPE_PARENT
) {
850 $this->peeringServiceManagers
[] = $manager;
852 if ($peering == self
::SCOPE_CHILD
) {
853 $manager->peeringServiceManagers
[] = $this;
861 * @param string $name
864 protected function canonicalizeName($name)
866 if (isset($this->canonicalNames
[$name])) {
867 return $this->canonicalNames
[$name];
870 // this is just for performance instead of using str_replace
871 return $this->canonicalNames
[$name] = strtolower(strtr($name, $this->canonicalNamesReplacements
));
875 * Create service via callback
877 * @param callable $callable
878 * @param string $cName
879 * @param string $rName
880 * @throws Exception\ServiceNotCreatedException
881 * @throws Exception\ServiceNotFoundException
882 * @throws Exception\CircularDependencyFoundException
885 protected function createServiceViaCallback($callable, $cName, $rName)
887 static $circularDependencyResolver = array();
888 $depKey = spl_object_hash($this) . '-' . $cName;
890 if (isset($circularDependencyResolver[$depKey])) {
891 $circularDependencyResolver = array();
892 throw new Exception\
CircularDependencyFoundException('Circular dependency for LazyServiceLoader was found for instance ' . $rName);
896 $circularDependencyResolver[$depKey] = true;
897 $instance = call_user_func($callable, $this, $cName, $rName);
898 unset($circularDependencyResolver[$depKey]);
899 } catch (Exception\ServiceNotFoundException
$e) {
900 unset($circularDependencyResolver[$depKey]);
902 } catch (\Exception
$e) {
903 unset($circularDependencyResolver[$depKey]);
904 throw new Exception\
ServiceNotCreatedException(
905 sprintf('An exception was raised while creating "%s"; no instance returned', $rName),
910 if ($instance === null) {
911 throw new Exception\
ServiceNotCreatedException('The factory was called but did not return an instance.');
918 * Retrieve a keyed list of all registered services. Handy for debugging!
922 public function getRegisteredServices()
925 'invokableClasses' => array_keys($this->invokableClasses
),
926 'factories' => array_keys($this->factories
),
927 'aliases' => array_keys($this->aliases
),
928 'instances' => array_keys($this->instances
),
933 * Retrieve a keyed list of all canonical names. Handy for debugging!
937 public function getCanonicalNames()
939 return $this->canonicalNames
;
943 * Allows to override the canonical names lookup map with predefined
946 * @param array $canonicalNames
947 * @return ServiceManager
949 public function setCanonicalNames($canonicalNames)
951 $this->canonicalNames
= $canonicalNames;
957 * Attempt to retrieve an instance via a peering manager
959 * @param string $name
962 protected function retrieveFromPeeringManager($name)
964 foreach ($this->peeringServiceManagers
as $peeringServiceManager) {
965 if ($peeringServiceManager->has($name)) {
966 return $peeringServiceManager->get($name);
970 $name = $this->canonicalizeName($name);
972 if ($this->hasAlias($name)) {
974 $name = $this->aliases
[$name];
975 } while ($this->hasAlias($name));
978 foreach ($this->peeringServiceManagers
as $peeringServiceManager) {
979 if ($peeringServiceManager->has($name)) {
980 return $peeringServiceManager->get($name);
988 * Attempt to create an instance via an invokable class
990 * @param string $canonicalName
991 * @param string $requestedName
992 * @return null|\stdClass
993 * @throws Exception\ServiceNotFoundException If resolved class does not exist
995 protected function createFromInvokable($canonicalName, $requestedName)
997 $invokable = $this->invokableClasses
[$canonicalName];
998 if (!class_exists($invokable)) {
999 throw new Exception\
ServiceNotFoundException(sprintf(
1000 '%s: failed retrieving "%s%s" via invokable class "%s"; class does not exist',
1001 get_class($this) . '::' . __FUNCTION__
,
1003 ($requestedName ?
'(alias: ' . $requestedName . ')' : ''),
1007 $instance = new $invokable;
1012 * Attempt to create an instance via a factory
1014 * @param string $canonicalName
1015 * @param string $requestedName
1017 * @throws Exception\ServiceNotCreatedException If factory is not callable
1019 protected function createFromFactory($canonicalName, $requestedName)
1021 $factory = $this->factories
[$canonicalName];
1022 if (is_string($factory) && class_exists($factory, true)) {
1023 $factory = new $factory;
1024 $this->factories
[$canonicalName] = $factory;
1026 if ($factory instanceof FactoryInterface
) {
1027 $instance = $this->createServiceViaCallback(array($factory, 'createService'), $canonicalName, $requestedName);
1028 } elseif (is_callable($factory)) {
1029 $instance = $this->createServiceViaCallback($factory, $canonicalName, $requestedName);
1031 throw new Exception\
ServiceNotCreatedException(sprintf(
1032 'While attempting to create %s%s an invalid factory was registered for this instance type.',
1034 ($requestedName ?
'(alias: ' . $requestedName . ')' : '')
1041 * Attempt to create an instance via an abstract factory
1043 * @param string $canonicalName
1044 * @param string $requestedName
1045 * @return object|null
1046 * @throws Exception\ServiceNotCreatedException If abstract factory is not callable
1048 protected function createFromAbstractFactory($canonicalName, $requestedName)
1050 foreach ($this->abstractFactories
as $index => $abstractFactory) {
1051 // support factories as strings
1052 if (is_string($abstractFactory) && class_exists($abstractFactory, true)) {
1053 $this->abstractFactories
[$index] = $abstractFactory = new $abstractFactory;
1054 } elseif (!$abstractFactory instanceof AbstractFactoryInterface
) {
1055 throw new Exception\
ServiceNotCreatedException(sprintf(
1056 'While attempting to create %s%s an abstract factory could not produce a valid instance.',
1058 ($requestedName ?
'(alias: ' . $requestedName . ')' : '')
1062 if ($abstractFactory->canCreateServiceWithName($this, $canonicalName, $requestedName)) {
1063 $this->pendingAbstractFactoryRequests
[get_class($abstractFactory)] = $requestedName;
1064 $instance = $this->createServiceViaCallback(
1065 array($abstractFactory, 'createServiceWithName'),
1069 unset($this->pendingAbstractFactoryRequests
[get_class($abstractFactory)]);
1073 } catch (\Exception
$e) {
1074 unset($this->pendingAbstractFactoryRequests
[get_class($abstractFactory)]);
1075 throw new Exception\
ServiceNotCreatedException(
1077 'An abstract factory could not create an instance of %s%s.',
1079 ($requestedName ?
'(alias: ' . $requestedName . ')' : '')
1085 if ($instance !== null) {
1092 * @param $canonicalName
1093 * @param $requestedName
1095 * @throws Exception\ServiceNotCreatedException
1097 protected function createDelegatorFromFactory($canonicalName, $requestedName)
1099 $serviceManager = $this;
1100 $delegatorsCount = count($this->delegators
[$canonicalName]);
1101 $creationCallback = function () use ($serviceManager, $requestedName, $canonicalName) {
1102 return $serviceManager->doCreate($requestedName, $canonicalName);
1105 for ($i = 0; $i < $delegatorsCount; $i +
= 1) {
1107 $delegatorFactory = $this->delegators
[$canonicalName][$i];
1109 if (is_string($delegatorFactory)) {
1110 $delegatorFactory = !$this->has($delegatorFactory) && class_exists($delegatorFactory, true) ?
1111 new $delegatorFactory
1112 : $this->get($delegatorFactory);
1113 $this->delegators
[$canonicalName][$i] = $delegatorFactory;
1116 if (!$delegatorFactory instanceof DelegatorFactoryInterface
&& !is_callable($delegatorFactory)) {
1117 throw new Exception\
ServiceNotCreatedException(sprintf(
1118 'While attempting to create %s%s an invalid factory was registered for this instance type.',
1120 ($requestedName ?
'(alias: ' . $requestedName . ')' : '')
1124 $creationCallback = $this->createDelegatorCallback(
1132 return $creationCallback($serviceManager, $canonicalName, $requestedName, $creationCallback);
1136 * Checks if the object has this class as one of its parents
1138 * @see https://bugs.php.net/bug.php?id=53727
1139 * @see https://github.com/zendframework/zf2/pull/1807
1141 * @param string $className
1142 * @param string $type
1145 * @deprecated this method is being deprecated as of zendframework 2.2, and may be removed in future major versions
1147 protected static function isSubclassOf($className, $type)
1149 if (is_subclass_of($className, $type)) {
1152 if (version_compare(PHP_VERSION
, '5.3.7', '>=')) {
1155 if (!interface_exists($type)) {
1158 $r = new ReflectionClass($className);
1159 return $r->implementsInterface($type);
1163 * Unregister a service
1165 * Called when $allowOverride is true and we detect that a service being
1166 * added to the instance already exists. This will remove the duplicate
1167 * entry, and also any shared flags previously registered.
1169 * @param string $canonical
1172 protected function unregisterService($canonical)
1174 $types = array('invokableClasses', 'factories', 'aliases');
1175 foreach ($types as $type) {
1176 if (isset($this->{$type}[$canonical])) {
1177 unset($this->{$type}[$canonical]);
1182 if (isset($this->instances
[$canonical])) {
1183 unset($this->instances
[$canonical]);
1186 if (isset($this->shared
[$canonical])) {
1187 unset($this->shared
[$canonical]);