4 * This file is part of the Symfony package.
6 * (c) Fabien Potencier <fabien@symfony.com>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Symfony\Component\DependencyInjection;
14 use Symfony\Component\DependencyInjection\Compiler\Compiler;
15 use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
16 use Symfony\Component\DependencyInjection\Compiler\PassConfig;
17 use Symfony\Component\DependencyInjection\Exception\BadMethodCallException;
18 use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
19 use Symfony\Component\DependencyInjection\Exception\LogicException;
20 use Symfony\Component\DependencyInjection\Exception\RuntimeException;
21 use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
22 use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
23 use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
24 use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
25 use Symfony\Component\Config\Resource\FileResource;
26 use Symfony\Component\Config\Resource\ResourceInterface;
27 use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\InstantiatorInterface;
28 use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\RealServiceInstantiator;
29 use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
30 use Symfony\Component\ExpressionLanguage\Expression;
31 use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
34 * ContainerBuilder is a DI container that provides an API to easily describe services.
36 * @author Fabien Potencier <fabien@symfony.com>
38 class ContainerBuilder extends Container implements TaggedContainerInterface
41 * @var ExtensionInterface[]
43 private $extensions = array();
46 * @var ExtensionInterface[]
48 private $extensionsByNs = array();
53 private $definitions = array();
58 private $aliasDefinitions = array();
61 * @var ResourceInterface[]
63 private $resources = array();
65 private $extensionConfigs = array();
72 private $trackResources;
75 * @var InstantiatorInterface|null
77 private $proxyInstantiator;
80 * @var ExpressionLanguage|null
82 private $expressionLanguage;
85 * @var ExpressionFunctionProviderInterface[]
87 private $expressionLanguageProviders = array();
89 public function __construct(ParameterBagInterface $parameterBag = null)
91 parent::__construct($parameterBag);
93 $this->trackResources = interface_exists('Symfony\Component\Config\Resource\ResourceInterface');
97 * @var string[] with tag names used by findTaggedServiceIds
99 private $usedTags = array();
102 * @var string[][] a map of env var names to their placeholders
104 private $envPlaceholders = array();
107 * @var int[] a map of env vars to their resolution counter
109 private $envCounters = array();
112 * Sets the track resources flag.
114 * If you are not using the loaders and therefore don't want
115 * to depend on the Config component, set this flag to false.
117 * @param bool $track true if you want to track resources, false otherwise
119 public function setResourceTracking($track)
121 $this->trackResources = (bool) $track;
125 * Checks if resources are tracked.
127 * @return bool true if resources are tracked, false otherwise
129 public function isTrackingResources()
131 return $this->trackResources;
135 * Sets the instantiator to be used when fetching proxies.
137 * @param InstantiatorInterface $proxyInstantiator
139 public function setProxyInstantiator(InstantiatorInterface $proxyInstantiator)
141 $this->proxyInstantiator = $proxyInstantiator;
145 * Registers an extension.
147 * @param ExtensionInterface $extension An extension instance
149 public function registerExtension(ExtensionInterface $extension)
151 $this->extensions[$extension->getAlias()] = $extension;
153 if (false !== $extension->getNamespace()) {
154 $this->extensionsByNs[$extension->getNamespace()] = $extension;
159 * Returns an extension by alias or namespace.
161 * @param string $name An alias or a namespace
163 * @return ExtensionInterface An extension instance
165 * @throws LogicException if the extension is not registered
167 public function getExtension($name)
169 if (isset($this->extensions[$name])) {
170 return $this->extensions[$name];
173 if (isset($this->extensionsByNs[$name])) {
174 return $this->extensionsByNs[$name];
177 throw new LogicException(sprintf('Container extension "%s" is not registered', $name));
181 * Returns all registered extensions.
183 * @return ExtensionInterface[] An array of ExtensionInterface
185 public function getExtensions()
187 return $this->extensions;
191 * Checks if we have an extension.
193 * @param string $name The name of the extension
195 * @return bool If the extension exists
197 public function hasExtension($name)
199 return isset($this->extensions[$name]) || isset($this->extensionsByNs[$name]);
203 * Returns an array of resources loaded to build this configuration.
205 * @return ResourceInterface[] An array of resources
207 public function getResources()
209 return array_unique($this->resources);
213 * Adds a resource for this configuration.
215 * @param ResourceInterface $resource A resource instance
219 public function addResource(ResourceInterface $resource)
221 if (!$this->trackResources) {
225 $this->resources[] = $resource;
231 * Sets the resources for this configuration.
233 * @param ResourceInterface[] $resources An array of resources
237 public function setResources(array $resources)
239 if (!$this->trackResources) {
243 $this->resources = $resources;
249 * Adds the object class hierarchy as resources.
251 * @param object $object An object instance
255 public function addObjectResource($object)
257 if ($this->trackResources) {
258 $this->addClassResource(new \ReflectionClass($object));
265 * Adds the given class hierarchy as resources.
267 * @param \ReflectionClass $class
271 public function addClassResource(\ReflectionClass $class)
273 if (!$this->trackResources) {
278 if (is_file($class->getFileName())) {
279 $this->addResource(new FileResource($class->getFileName()));
281 } while ($class = $class->getParentClass());
287 * Loads the configuration for an extension.
289 * @param string $extension The extension alias or namespace
290 * @param array $values An array of values that customizes the extension
294 * @throws BadMethodCallException When this ContainerBuilder is frozen
295 * @throws \LogicException if the container is frozen
297 public function loadFromExtension($extension, array $values = array())
299 if ($this->isFrozen()) {
300 throw new BadMethodCallException('Cannot load from an extension on a frozen container.');
303 $namespace = $this->getExtension($extension)->getAlias();
305 $this->extensionConfigs[$namespace][] = $values;
311 * Adds a compiler pass.
313 * @param CompilerPassInterface $pass A compiler pass
314 * @param string $type The type of compiler pass
315 * @param int $priority Used to sort the passes
319 public function addCompilerPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION/*, $priority = 0*/)
321 if (func_num_args() >= 3) {
322 $priority = func_get_arg(2);
324 if (__CLASS__ !== get_class($this)) {
325 $r = new \ReflectionMethod($this, __FUNCTION__);
326 if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
327 @trigger_error(sprintf('Method %s() will have a third `$priority = 0` argument in version 4.0. Not defining it is deprecated since 3.2.', __METHOD__), E_USER_DEPRECATED);
334 $this->getCompiler()->addPass($pass, $type, $priority);
336 $this->addObjectResource($pass);
342 * Returns the compiler pass config which can then be modified.
344 * @return PassConfig The compiler pass config
346 public function getCompilerPassConfig()
348 return $this->getCompiler()->getPassConfig();
352 * Returns the compiler.
354 * @return Compiler The compiler
356 public function getCompiler()
358 if (null === $this->compiler) {
359 $this->compiler = new Compiler();
362 return $this->compiler;
368 * @param string $id The service identifier
369 * @param object $service The service instance
371 * @throws BadMethodCallException When this ContainerBuilder is frozen
373 public function set($id, $service)
375 $id = strtolower($id);
377 if ($this->isFrozen() && (isset($this->definitions[$id]) && !$this->definitions[$id]->isSynthetic())) {
378 // setting a synthetic service on a frozen container is alright
379 throw new BadMethodCallException(sprintf('Setting service "%s" for an unknown or non-synthetic service definition on a frozen container is not allowed.', $id));
382 unset($this->definitions[$id], $this->aliasDefinitions[$id]);
384 parent::set($id, $service);
388 * Removes a service definition.
390 * @param string $id The service identifier
392 public function removeDefinition($id)
394 unset($this->definitions[strtolower($id)]);
398 * Returns true if the given service is defined.
400 * @param string $id The service identifier
402 * @return bool true if the service is defined, false otherwise
404 public function has($id)
406 $id = strtolower($id);
408 return isset($this->definitions[$id]) || isset($this->aliasDefinitions[$id]) || parent::has($id);
414 * @param string $id The service identifier
415 * @param int $invalidBehavior The behavior when the service does not exist
417 * @return object The associated service
419 * @throws InvalidArgumentException when no definitions are available
420 * @throws ServiceCircularReferenceException When a circular reference is detected
421 * @throws ServiceNotFoundException When the service is not defined
426 public function get($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE)
428 $id = strtolower($id);
430 if ($service = parent::get($id, ContainerInterface::NULL_ON_INVALID_REFERENCE)) {
434 if (!isset($this->definitions[$id]) && isset($this->aliasDefinitions[$id])) {
435 return $this->get((string) $this->aliasDefinitions[$id], $invalidBehavior);
439 $definition = $this->getDefinition($id);
440 } catch (ServiceNotFoundException $e) {
441 if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) {
448 $this->loading[$id] = true;
451 $service = $this->createService($definition, $id);
453 unset($this->loading[$id]);
460 * Merges a ContainerBuilder with the current ContainerBuilder configuration.
462 * Service definitions overrides the current defined ones.
464 * But for parameters, they are overridden by the current ones. It allows
465 * the parameters passed to the container constructor to have precedence
466 * over the loaded ones.
468 * $container = new ContainerBuilder(array('foo' => 'bar'));
469 * $loader = new LoaderXXX($container);
470 * $loader->load('resource_name');
471 * $container->register('foo', new stdClass());
473 * In the above example, even if the loaded resource defines a foo
474 * parameter, the value will still be 'bar' as defined in the ContainerBuilder
477 * @param ContainerBuilder $container The ContainerBuilder instance to merge
479 * @throws BadMethodCallException When this ContainerBuilder is frozen
481 public function merge(ContainerBuilder $container)
483 if ($this->isFrozen()) {
484 throw new BadMethodCallException('Cannot merge on a frozen container.');
487 $this->addDefinitions($container->getDefinitions());
488 $this->addAliases($container->getAliases());
489 $this->getParameterBag()->add($container->getParameterBag()->all());
491 if ($this->trackResources) {
492 foreach ($container->getResources() as $resource) {
493 $this->addResource($resource);
497 foreach ($this->extensions as $name => $extension) {
498 if (!isset($this->extensionConfigs[$name])) {
499 $this->extensionConfigs[$name] = array();
502 $this->extensionConfigs[$name] = array_merge($this->extensionConfigs[$name], $container->getExtensionConfig($name));
505 if ($this->getParameterBag() instanceof EnvPlaceholderParameterBag && $container->getParameterBag() instanceof EnvPlaceholderParameterBag) {
506 $this->getParameterBag()->mergeEnvPlaceholders($container->getParameterBag());
509 foreach ($container->envCounters as $env => $count) {
510 if (!isset($this->envCounters[$env])) {
511 $this->envCounters[$env] = $count;
513 $this->envCounters[$env] += $count;
519 * Returns the configuration array for the given extension.
521 * @param string $name The name of the extension
523 * @return array An array of configuration
525 public function getExtensionConfig($name)
527 if (!isset($this->extensionConfigs[$name])) {
528 $this->extensionConfigs[$name] = array();
531 return $this->extensionConfigs[$name];
535 * Prepends a config array to the configs of the given extension.
537 * @param string $name The name of the extension
538 * @param array $config The config to set
540 public function prependExtensionConfig($name, array $config)
542 if (!isset($this->extensionConfigs[$name])) {
543 $this->extensionConfigs[$name] = array();
546 array_unshift($this->extensionConfigs[$name], $config);
550 * Compiles the container.
552 * This method passes the container to compiler
553 * passes whose job is to manipulate and optimize
556 * The main compiler passes roughly do four things:
558 * * The extension configurations are merged;
559 * * Parameter values are resolved;
560 * * The parameter bag is frozen;
561 * * Extension loading is disabled.
563 public function compile()
565 $compiler = $this->getCompiler();
567 if ($this->trackResources) {
568 foreach ($compiler->getPassConfig()->getPasses() as $pass) {
569 $this->addObjectResource($pass);
573 $compiler->compile($this);
575 foreach ($this->definitions as $id => $definition) {
576 if ($this->trackResources && $definition->isLazy() && ($class = $definition->getClass()) && class_exists($class)) {
577 $this->addClassResource(new \ReflectionClass($class));
581 $this->extensionConfigs = array();
582 $bag = $this->getParameterBag();
586 $this->envPlaceholders = $bag instanceof EnvPlaceholderParameterBag ? $bag->getEnvPlaceholders() : array();
590 * Gets all service ids.
592 * @return array An array of all defined service ids
594 public function getServiceIds()
596 return array_unique(array_merge(array_keys($this->getDefinitions()), array_keys($this->aliasDefinitions), parent::getServiceIds()));
600 * Adds the service aliases.
602 * @param array $aliases An array of aliases
604 public function addAliases(array $aliases)
606 foreach ($aliases as $alias => $id) {
607 $this->setAlias($alias, $id);
612 * Sets the service aliases.
614 * @param array $aliases An array of aliases
616 public function setAliases(array $aliases)
618 $this->aliasDefinitions = array();
619 $this->addAliases($aliases);
623 * Sets an alias for an existing service.
625 * @param string $alias The alias to create
626 * @param string|Alias $id The service to alias
628 * @throws InvalidArgumentException if the id is not a string or an Alias
629 * @throws InvalidArgumentException if the alias is for itself
631 public function setAlias($alias, $id)
633 $alias = strtolower($alias);
635 if (is_string($id)) {
636 $id = new Alias($id);
637 } elseif (!$id instanceof Alias) {
638 throw new InvalidArgumentException('$id must be a string, or an Alias object.');
641 if ($alias === (string) $id) {
642 throw new InvalidArgumentException(sprintf('An alias can not reference itself, got a circular reference on "%s".', $alias));
645 unset($this->definitions[$alias]);
647 $this->aliasDefinitions[$alias] = $id;
653 * @param string $alias The alias to remove
655 public function removeAlias($alias)
657 unset($this->aliasDefinitions[strtolower($alias)]);
661 * Returns true if an alias exists under the given identifier.
663 * @param string $id The service identifier
665 * @return bool true if the alias exists, false otherwise
667 public function hasAlias($id)
669 return isset($this->aliasDefinitions[strtolower($id)]);
673 * Gets all defined aliases.
675 * @return Alias[] An array of aliases
677 public function getAliases()
679 return $this->aliasDefinitions;
685 * @param string $id The service identifier
687 * @return Alias An Alias instance
689 * @throws InvalidArgumentException if the alias does not exist
691 public function getAlias($id)
693 $id = strtolower($id);
695 if (!isset($this->aliasDefinitions[$id])) {
696 throw new InvalidArgumentException(sprintf('The service alias "%s" does not exist.', $id));
699 return $this->aliasDefinitions[$id];
703 * Registers a service definition.
705 * This methods allows for simple registration of service definition
706 * with a fluid interface.
708 * @param string $id The service identifier
709 * @param string $class The service class
711 * @return Definition A Definition instance
713 public function register($id, $class = null)
715 return $this->setDefinition($id, new Definition($class));
719 * Adds the service definitions.
721 * @param Definition[] $definitions An array of service definitions
723 public function addDefinitions(array $definitions)
725 foreach ($definitions as $id => $definition) {
726 $this->setDefinition($id, $definition);
731 * Sets the service definitions.
733 * @param Definition[] $definitions An array of service definitions
735 public function setDefinitions(array $definitions)
737 $this->definitions = array();
738 $this->addDefinitions($definitions);
742 * Gets all service definitions.
744 * @return Definition[] An array of Definition instances
746 public function getDefinitions()
748 return $this->definitions;
752 * Sets a service definition.
754 * @param string $id The service identifier
755 * @param Definition $definition A Definition instance
757 * @return Definition the service definition
759 * @throws BadMethodCallException When this ContainerBuilder is frozen
761 public function setDefinition($id, Definition $definition)
763 if ($this->isFrozen()) {
764 throw new BadMethodCallException('Adding definition to a frozen container is not allowed');
767 $id = strtolower($id);
769 unset($this->aliasDefinitions[$id]);
771 return $this->definitions[$id] = $definition;
775 * Returns true if a service definition exists under the given identifier.
777 * @param string $id The service identifier
779 * @return bool true if the service definition exists, false otherwise
781 public function hasDefinition($id)
783 return isset($this->definitions[strtolower($id)]);
787 * Gets a service definition.
789 * @param string $id The service identifier
791 * @return Definition A Definition instance
793 * @throws ServiceNotFoundException if the service definition does not exist
795 public function getDefinition($id)
797 $id = strtolower($id);
799 if (!isset($this->definitions[$id])) {
800 throw new ServiceNotFoundException($id);
803 return $this->definitions[$id];
807 * Gets a service definition by id or alias.
809 * The method "unaliases" recursively to return a Definition instance.
811 * @param string $id The service identifier or alias
813 * @return Definition A Definition instance
815 * @throws ServiceNotFoundException if the service definition does not exist
817 public function findDefinition($id)
819 $id = strtolower($id);
821 while (isset($this->aliasDefinitions[$id])) {
822 $id = (string) $this->aliasDefinitions[$id];
825 return $this->getDefinition($id);
829 * Creates a service for a service definition.
831 * @param Definition $definition A service definition instance
832 * @param string $id The service identifier
833 * @param bool $tryProxy Whether to try proxying the service with a lazy proxy
835 * @return object The service described by the service definition
837 * @throws RuntimeException When the factory definition is incomplete
838 * @throws RuntimeException When the service is a synthetic service
839 * @throws InvalidArgumentException When configure callable is not callable
841 private function createService(Definition $definition, $id, $tryProxy = true)
843 if ($definition instanceof DefinitionDecorator) {
844 throw new RuntimeException(sprintf('Constructing service "%s" from a parent definition is not supported at build time.', $id));
847 if ($definition->isSynthetic()) {
848 throw new RuntimeException(sprintf('You have requested a synthetic service ("%s"). The DIC does not know how to construct this service.', $id));
851 if ($definition->isDeprecated()) {
852 @trigger_error($definition->getDeprecationMessage($id), E_USER_DEPRECATED);
855 if ($tryProxy && $definition->isLazy()) {
857 ->getProxyInstantiator()
861 $id, function () use ($definition, $id) {
862 return $this->createService($definition, $id, false);
865 $this->shareService($definition, $proxy, $id);
870 $parameterBag = $this->getParameterBag();
872 if (null !== $definition->getFile()) {
873 require_once $parameterBag->resolveValue($definition->getFile());
876 $arguments = $this->resolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getArguments())));
878 if (null !== $factory = $definition->getFactory()) {
879 if (is_array($factory)) {
880 $factory = array($this->resolveServices($parameterBag->resolveValue($factory[0])), $factory[1]);
881 } elseif (!is_string($factory)) {
882 throw new RuntimeException(sprintf('Cannot create service "%s" because of invalid factory', $id));
885 $service = call_user_func_array($factory, $arguments);
887 if (!$definition->isDeprecated() && is_array($factory) && is_string($factory[0])) {
888 $r = new \ReflectionClass($factory[0]);
890 if (0 < strpos($r->getDocComment(), "\n * @deprecated ")) {
891 @trigger_error(sprintf('The "%s" service relies on the deprecated "%s" factory class. It should either be deprecated or its factory upgraded.', $id, $r->name), E_USER_DEPRECATED);
895 $r = new \ReflectionClass($parameterBag->resolveValue($definition->getClass()));
897 $service = null === $r->getConstructor() ? $r->newInstance() : $r->newInstanceArgs($arguments);
899 if (!$definition->isDeprecated() && 0 < strpos($r->getDocComment(), "\n * @deprecated ")) {
900 @trigger_error(sprintf('The "%s" service relies on the deprecated "%s" class. It should either be deprecated or its implementation upgraded.', $id, $r->name), E_USER_DEPRECATED);
904 if ($tryProxy || !$definition->isLazy()) {
905 // share only if proxying failed, or if not a proxy
906 $this->shareService($definition, $service, $id);
909 $properties = $this->resolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getProperties())));
910 foreach ($properties as $name => $value) {
911 $service->$name = $value;
914 foreach ($definition->getMethodCalls() as $call) {
915 $this->callMethod($service, $call);
918 if ($callable = $definition->getConfigurator()) {
919 if (is_array($callable)) {
920 $callable[0] = $parameterBag->resolveValue($callable[0]);
922 if ($callable[0] instanceof Reference) {
923 $callable[0] = $this->get((string) $callable[0], $callable[0]->getInvalidBehavior());
924 } elseif ($callable[0] instanceof Definition) {
925 $callable[0] = $this->createService($callable[0], null);
929 if (!is_callable($callable)) {
930 throw new InvalidArgumentException(sprintf('The configure callable for class "%s" is not a callable.', get_class($service)));
933 call_user_func($callable, $service);
940 * Replaces service references by the real service instance and evaluates expressions.
942 * @param mixed $value A value
944 * @return mixed The same value with all service references replaced by
945 * the real service instances and all expressions evaluated
947 public function resolveServices($value)
949 if (is_array($value)) {
950 foreach ($value as $k => $v) {
951 $value[$k] = $this->resolveServices($v);
953 } elseif ($value instanceof Reference) {
954 $value = $this->get((string) $value, $value->getInvalidBehavior());
955 } elseif ($value instanceof Definition) {
956 $value = $this->createService($value, null);
957 } elseif ($value instanceof Expression) {
958 $value = $this->getExpressionLanguage()->evaluate($value, array('container' => $this));
965 * Returns service ids for a given tag.
969 * $container->register('foo')->addTag('my.tag', array('hello' => 'world'));
971 * $serviceIds = $container->findTaggedServiceIds('my.tag');
972 * foreach ($serviceIds as $serviceId => $tags) {
973 * foreach ($tags as $tag) {
974 * echo $tag['hello'];
978 * @param string $name The tag name
980 * @return array An array of tags with the tagged service as key, holding a list of attribute arrays
982 public function findTaggedServiceIds($name)
984 $this->usedTags[] = $name;
986 foreach ($this->getDefinitions() as $id => $definition) {
987 if ($definition->hasTag($name)) {
988 $tags[$id] = $definition->getTag($name);
996 * Returns all tags the defined services use.
998 * @return array An array of tags
1000 public function findTags()
1003 foreach ($this->getDefinitions() as $id => $definition) {
1004 $tags = array_merge(array_keys($definition->getTags()), $tags);
1007 return array_unique($tags);
1011 * Returns all tags not queried by findTaggedServiceIds.
1013 * @return string[] An array of tags
1015 public function findUnusedTags()
1017 return array_values(array_diff($this->findTags(), $this->usedTags));
1020 public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider)
1022 $this->expressionLanguageProviders[] = $provider;
1026 * @return ExpressionFunctionProviderInterface[]
1028 public function getExpressionLanguageProviders()
1030 return $this->expressionLanguageProviders;
1034 * Resolves env parameter placeholders in a string or an array.
1036 * @param mixed $value The value to resolve
1037 * @param string|null $format A sprintf() format to use as replacement for env placeholders or null to use the default parameter format
1038 * @param array &$usedEnvs Env vars found while resolving are added to this array
1040 * @return string The string with env parameters resolved
1042 public function resolveEnvPlaceholders($value, $format = null, array &$usedEnvs = null)
1044 if (null === $format) {
1045 $format = '%%env(%s)%%';
1048 if (is_array($value)) {
1050 foreach ($value as $k => $v) {
1051 $result[$this->resolveEnvPlaceholders($k, $format, $usedEnvs)] = $this->resolveEnvPlaceholders($v, $format, $usedEnvs);
1057 if (!is_string($value)) {
1061 $bag = $this->getParameterBag();
1062 $envPlaceholders = $bag instanceof EnvPlaceholderParameterBag ? $bag->getEnvPlaceholders() : $this->envPlaceholders;
1064 foreach ($envPlaceholders as $env => $placeholders) {
1065 foreach ($placeholders as $placeholder) {
1066 if (false !== stripos($value, $placeholder)) {
1067 $value = str_ireplace($placeholder, sprintf($format, $env), $value);
1068 $usedEnvs[$env] = $env;
1069 $this->envCounters[$env] = isset($this->envCounters[$env]) ? 1 + $this->envCounters[$env] : 1;
1078 * Get statistics about env usage.
1080 * @return int[] The number of time each env vars has been resolved
1082 public function getEnvCounters()
1084 $bag = $this->getParameterBag();
1085 $envPlaceholders = $bag instanceof EnvPlaceholderParameterBag ? $bag->getEnvPlaceholders() : $this->envPlaceholders;
1087 foreach ($envPlaceholders as $env => $placeholders) {
1088 if (!isset($this->envCounters[$env])) {
1089 $this->envCounters[$env] = 0;
1093 return $this->envCounters;
1097 * Returns the Service Conditionals.
1099 * @param mixed $value An array of conditionals to return
1101 * @return array An array of Service conditionals
1103 public static function getServiceConditionals($value)
1105 $services = array();
1107 if (is_array($value)) {
1108 foreach ($value as $v) {
1109 $services = array_unique(array_merge($services, self::getServiceConditionals($v)));
1111 } elseif ($value instanceof Reference && $value->getInvalidBehavior() === ContainerInterface::IGNORE_ON_INVALID_REFERENCE) {
1112 $services[] = (string) $value;
1119 * Retrieves the currently set proxy instantiator or instantiates one.
1121 * @return InstantiatorInterface
1123 private function getProxyInstantiator()
1125 if (!$this->proxyInstantiator) {
1126 $this->proxyInstantiator = new RealServiceInstantiator();
1129 return $this->proxyInstantiator;
1132 private function callMethod($service, $call)
1134 $services = self::getServiceConditionals($call[1]);
1136 foreach ($services as $s) {
1137 if (!$this->has($s)) {
1142 call_user_func_array(array($service, $call[0]), $this->resolveServices($this->getParameterBag()->unescapeValue($this->getParameterBag()->resolveValue($call[1]))));
1146 * Shares a given service in the container.
1148 * @param Definition $definition
1149 * @param mixed $service
1150 * @param string|null $id
1152 private function shareService(Definition $definition, $service, $id)
1154 if (null !== $id && $definition->isShared()) {
1155 $this->services[strtolower($id)] = $service;
1159 private function getExpressionLanguage()
1161 if (null === $this->expressionLanguage) {
1162 if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) {
1163 throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
1165 $this->expressionLanguage = new ExpressionLanguage(null, $this->expressionLanguageProviders);
1168 return $this->expressionLanguage;