Added the zend framework 2 library, the path is specified in line no.26 in zend_modul...
[openemr.git] / interface / modules / zend_modules / library / Zend / ServiceManager / ServiceManager.php
blob2480eeb559eaae4b547bdc612fbd5ff229a9dffc
1 <?php
2 /**
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
8 */
10 namespace Zend\ServiceManager;
12 use ReflectionClass;
14 class ServiceManager implements ServiceLocatorInterface
17 /**@#+
18 * Constants
20 const SCOPE_PARENT = 'parent';
21 const SCOPE_CHILD = 'child';
22 /**@#-*/
24 /**
25 * Lookup for canonicalized names.
27 * @var array
29 protected $canonicalNames = array();
31 /**
32 * @var bool
34 protected $allowOverride = false;
36 /**
37 * @var array
39 protected $invokableClasses = array();
41 /**
42 * @var string|callable|\Closure|FactoryInterface[]
44 protected $factories = array();
46 /**
47 * @var AbstractFactoryInterface[]
49 protected $abstractFactories = array();
51 /**
52 * @var array[]
54 protected $delegators = array();
56 /**
57 * @var array
59 protected $pendingAbstractFactoryRequests = array();
61 /**
62 * @var string
64 protected $lastAbstractFactoryUsed = null;
66 /**
67 * @var string
69 protected $lastCanonicalNameUsed = null;
71 /**
72 * @var array
74 protected $shared = array();
76 /**
77 * Registered services and cached values
79 * @var array
81 protected $instances = array();
83 /**
84 * @var array
86 protected $aliases = array();
88 /**
89 * @var array
91 protected $initializers = array();
93 /**
94 * @var ServiceManager[]
96 protected $peeringServiceManagers = array();
98 /**
99 * Whether or not to share by default
101 * @var bool
103 protected $shareByDefault = true;
106 * @var bool
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('-' => '', '_' => '', ' ' => '', '\\' => '', '/' => '');
121 * Constructor
123 * @param ConfigInterface $config
125 public function __construct(ConfigInterface $config = null)
127 if ($config) {
128 $config->configureServiceManager($this);
133 * Set allow override
135 * @param $allowOverride
136 * @return ServiceManager
138 public function setAllowOverride($allowOverride)
140 $this->allowOverride = (bool) $allowOverride;
141 return $this;
145 * Get allow override
147 * @return bool
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;
170 return $this;
174 * Are services shared by default?
176 * @return bool
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;
192 return $this;
196 * Get throw exceptions in create
198 * @return bool
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;
214 return $this;
218 * Should we retrieve from the peering manager prior to attempting to create a service?
220 * @return bool
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',
244 $name
247 $this->unregisterService($cName);
250 if ($shared === null) {
251 $shared = $this->shareByDefault;
254 $this->invokableClasses[$cName] = $invokableClass;
255 $this->shared[$cName] = (bool) $shared;
257 return $this;
261 * Set factory
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',
284 $name
287 $this->unregisterService($cName);
290 if ($shared === null) {
291 $shared = $this->shareByDefault;
294 $this->factories[$cName] = $factory;
295 $this->shared[$cName] = (bool) $shared;
297 return $this;
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.'
321 if ($topOfStack) {
322 array_unshift($this->abstractFactories, $factory);
323 } else {
324 array_push($this->abstractFactories, $factory);
326 return $this;
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;
347 return $this;
351 * Add initializer
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.');
370 if ($topOfStack) {
371 array_unshift($this->initializers, $initializer);
372 } else {
373 array_push($this->initializers, $initializer);
375 return $this;
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__,
395 $name
398 $this->unregisterService($cName);
401 $this->instances[$cName] = $service;
403 return $this;
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);
416 if (
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__,
424 $name
428 $this->shared[$cName] = (bool) $isShared;
429 return $this;
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)
440 $stack = array();
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),
447 $cName
451 $stack[$cName] = $cName;
452 $cName = $this->aliases[$cName];
455 return $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];
471 } else {
472 $cName = $this->canonicalizeName($name);
475 $isAlias = false;
477 if ($this->hasAlias($cName)) {
478 $isAlias = true;
479 $cName = $this->resolveAlias($cName);
482 $instance = null;
484 if ($usePeeringServiceManagers && $this->retrieveFromPeeringManagerFirst) {
485 $instance = $this->retrieveFromPeeringManager($name);
487 if (null !== $instance) {
488 return $instance;
492 if (isset($this->instances[$cName])) {
493 return $this->instances[$cName];
496 if (!$instance) {
497 if (
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) {
511 if ($isAlias) {
512 throw new Exception\ServiceNotFoundException(sprintf(
513 'An alias "%s" was requested but no service could be found.',
514 $name
518 throw new Exception\ServiceNotFoundException(sprintf(
519 '%s was unable to fetch or create an instance for %s',
520 get_class($this) . '::' . __FUNCTION__,
521 $name
525 if (
526 ($this->shareByDefault && !isset($this->shared[$cName]))
527 || (isset($this->shared[$cName]) && $this->shared[$cName] === true)
529 $this->instances[$cName] = $instance;
532 return $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;
546 } else {
547 $rName = $name;
549 // inlined code from ServiceManager::canonicalizeName for performance
550 if (isset($this->canonicalNames[$rName])) {
551 $cName = $this->canonicalNames[$name];
552 } else {
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
572 * @return callable
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)
598 $instance = null;
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',
615 $cName,
616 ($rName ? '(alias: ' . $rName . ')' : '')
620 // Do not call initializers if we do not have an instance
621 if ($instance === null) {
622 return $instance;
625 foreach ($this->initializers as $initializer) {
626 if ($initializer instanceof InitializerInterface) {
627 $initializer->initialize($instance, $this);
628 } else {
629 call_user_func($initializer, $instance, $this);
633 return $instance;
637 * Determine if we can create an instance.
639 * @param string|array $name
640 * @param bool $checkAbstractFactories
641 * @return bool
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;
649 } else {
650 $rName = $name;
651 $cName = $this->canonicalizeName($rName);
654 return (
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
667 * @return bool
669 public function has($name, $checkAbstractFactories = true, $usePeeringServiceManagers = true)
671 if (is_array($name)) {
672 list($cName, $rName) = $name;
673 } else {
674 $rName = $name;
676 // inlined code from ServiceManager::canonicalizeName for performance
677 if (isset($this->canonicalNames[$rName])) {
678 $cName = $this->canonicalNames[$name];
679 } else {
680 $cName = $this->canonicalizeName($name);
684 if (
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))
691 return true;
694 if ($usePeeringServiceManagers) {
695 foreach ($this->peeringServiceManagers as $peeringServiceManager) {
696 if ($peeringServiceManager->has($rName)) {
697 return true;
702 return false;
706 * Determine if we can create an instance from an abstract factory.
708 * @param string $cName
709 * @param string $rName
710 * @return bool
712 public function canCreateFromAbstractFactory($cName, $rName)
714 // check abstract factories
715 foreach ($this->abstractFactories as $abstractFactory) {
716 $factoryClass = get_class($abstractFactory);
718 if (
719 isset($this->pendingAbstractFactoryRequests[$factoryClass])
720 && $this->pendingAbstractFactoryRequests[$factoryClass] == $rName
722 return false;
725 $objectHash = spl_object_hash($abstractFactory);
727 if ($this->lastAbstractFactoryUsed === $objectHash && $this->lastCanonicalNameUsed === $cName) {
728 $this->lastAbstractFactoryUsed = $this->lastCanonicalNameUsed = null;
729 return false;
732 $this->lastAbstractFactoryUsed = $objectHash;
733 $this->lastCanonicalNameUsed = $cName;
735 if ($abstractFactory->canCreateServiceWithName($this, $cName, $rName)) {
736 $this->lastAbstractFactoryUsed = $this->lastCanonicalNameUsed = null;
737 return true;
740 return false;
744 * Ensure the alias definition will not result in a circular reference
746 * @param string $alias
747 * @param string $nameOrAlias
748 * @throws Exception\CircularReferenceException
749 * @return self
751 protected function checkForCircularAliasReference($alias, $nameOrAlias)
753 $aliases = $this->aliases;
754 $aliases[$alias] = $nameOrAlias;
755 $stack = array();
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"',
761 $alias,
762 $nameOrAlias,
763 implode('" -> "', $stack),
764 $alias
768 $stack[$alias] = $alias;
769 $alias = $aliases[$alias];
772 return $this;
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',
798 $cAlias,
799 $alias
803 if ($this->hasAlias($alias)) {
804 $this->checkForCircularAliasReference($cAlias, $nameOrAlias);
807 $this->aliases[$cAlias] = $nameOrAlias;
808 return $this;
812 * Determine if we have an alias
814 * @param string $alias
815 * @return bool
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;
855 return $this;
859 * Canonicalize name
861 * @param string $name
862 * @return string
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
883 * @return object
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);
895 try {
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]);
901 throw $e;
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),
906 $e->getCode(),
910 if ($instance === null) {
911 throw new Exception\ServiceNotCreatedException('The factory was called but did not return an instance.');
914 return $instance;
918 * Retrieve a keyed list of all registered services. Handy for debugging!
920 * @return array
922 public function getRegisteredServices()
924 return array(
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!
935 * @return array
937 public function getCanonicalNames()
939 return $this->canonicalNames;
943 * Allows to override the canonical names lookup map with predefined
944 * values.
946 * @param array $canonicalNames
947 * @return ServiceManager
949 public function setCanonicalNames($canonicalNames)
951 $this->canonicalNames = $canonicalNames;
953 return $this;
957 * Attempt to retrieve an instance via a peering manager
959 * @param string $name
960 * @return mixed
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)) {
973 do {
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);
984 return null;
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__,
1002 $canonicalName,
1003 ($requestedName ? '(alias: ' . $requestedName . ')' : ''),
1004 $invokable
1007 $instance = new $invokable;
1008 return $instance;
1012 * Attempt to create an instance via a factory
1014 * @param string $canonicalName
1015 * @param string $requestedName
1016 * @return mixed
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);
1030 } else {
1031 throw new Exception\ServiceNotCreatedException(sprintf(
1032 'While attempting to create %s%s an invalid factory was registered for this instance type.',
1033 $canonicalName,
1034 ($requestedName ? '(alias: ' . $requestedName . ')' : '')
1037 return $instance;
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.',
1057 $canonicalName,
1058 ($requestedName ? '(alias: ' . $requestedName . ')' : '')
1061 try {
1062 if ($abstractFactory->canCreateServiceWithName($this, $canonicalName, $requestedName)) {
1063 $this->pendingAbstractFactoryRequests[get_class($abstractFactory)] = $requestedName;
1064 $instance = $this->createServiceViaCallback(
1065 array($abstractFactory, 'createServiceWithName'),
1066 $canonicalName,
1067 $requestedName
1069 unset($this->pendingAbstractFactoryRequests[get_class($abstractFactory)]);
1070 } else {
1071 $instance = null;
1073 } catch (\Exception $e) {
1074 unset($this->pendingAbstractFactoryRequests[get_class($abstractFactory)]);
1075 throw new Exception\ServiceNotCreatedException(
1076 sprintf(
1077 'An abstract factory could not create an instance of %s%s.',
1078 $canonicalName,
1079 ($requestedName ? '(alias: ' . $requestedName . ')' : '')
1081 $e->getCode(),
1085 if ($instance !== null) {
1086 return $instance;
1092 * @param $canonicalName
1093 * @param $requestedName
1094 * @return mixed
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.',
1119 $canonicalName,
1120 ($requestedName ? '(alias: ' . $requestedName . ')' : '')
1124 $creationCallback = $this->createDelegatorCallback(
1125 $delegatorFactory,
1126 $requestedName,
1127 $canonicalName,
1128 $creationCallback
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
1143 * @return bool
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)) {
1150 return true;
1152 if (version_compare(PHP_VERSION, '5.3.7', '>=')) {
1153 return false;
1155 if (!interface_exists($type)) {
1156 return false;
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
1170 * @return void
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]);
1178 break;
1182 if (isset($this->instances[$canonical])) {
1183 unset($this->instances[$canonical]);
1186 if (isset($this->shared[$canonical])) {
1187 unset($this->shared[$canonical]);