/** * Resolves function arguments to applicable arguments. * * This method will resolve all parameters in arguments as well as references to * other services (in the form of `@service_name`). * * @param array|mixed $argument Either an array of arguments or a single argument. * @param string $selfServiceName If the arguments can reference "self service name", the name of * such references service should be passed here. It can be referenced * in arguments as "@=". Default: `null`. * @return array|mixed */ public function resolve($argument, $selfServiceName = null) { // deeply resolve arguments if (is_array($argument)) { foreach ($argument as $i => $arg) { $argument[$i] = $this->resolve($arg, $selfServiceName); } return $argument; } // possible parameter argument if (is_string($argument)) { $argument = $this->parametersResolver->resolve($argument); } // if possible to reference self in arguments then do it // (reference by name instead of getting the service now) if ($selfServiceName !== null && $argument === '@') { $argument = '@' . $selfServiceName; } // if possible to reference self name in arguments then do it if ($selfServiceName !== null && $argument === '@=') { $argument = $selfServiceName; } // and maybe referencing a different service? if (is_string($argument) && mb_substr($argument, 0, 1) === '@') { $serviceName = mb_substr($argument, 1); $optional = mb_substr($argument, -1) === '?'; $serviceName = $optional ? mb_substr($serviceName, 0, -1) : $serviceName; try { $argument = $this->container->get($serviceName); } catch (ServiceNotFoundException $e) { if ($optional) { $argument = null; } else { throw new ServiceNotFoundException('Could not find service "' . $serviceName . '" when resolving a non-optional argument.', 0, $e); } } } return $argument; }
public function get($name) { $instance = parent::get($name); // if already loaded from cache, then don't do anything if ($this->loadedFromCache) { return $instance; } // if cache hasn't been loaded yet, then keep reference to this // resolved service so that on cache load we can deliver all // notifications to it $realName = $this->resolveServiceName($name); $this->preCacheServices[$realName] = array('name' => $realName, 'instance' => $instance); return $instance; }
/** * Instantiate the service and perform constructor injection if necessary. * * @param Service $service Service definition. * @return object */ protected function instantiateService(Service $service) { $name = $service->name; // if already resolved the definition, then just call the resolved closure factory if (isset($this->instantiateClosuresCache[$name])) { $instantiateClosure = $this->instantiateClosuresCache[$name]; return $instantiateClosure(); } // deal with closure services if ($service instanceof ClosureService) { $serviceClosure = $service->closure; return $serviceClosure($this->container); } // deal with object services if ($service instanceof ObjectService) { return $service->getInstance(); } // deal with factory services if ($service instanceof FactoryService) { try { $factoryServiceName = $this->parametersResolver->resolve($service->factoryService); $factoryServiceDefinition = $this->container->getDefinition($factoryServiceName); $factoryService = $this->container->get($factoryServiceName); return $this->callMethod($factoryServiceDefinition, $service->factoryMethod, $service->factoryArguments, $factoryService); } catch (Exception $e) { throw new InvalidServiceException('Could not instantiate service "' . $name . '" due to: ' . $e->getMessage(), 0, $e); } } // class can be defined as a parameter $class = $this->parametersResolver->resolve($service->class); if (!class_exists($class)) { throw new InvalidServiceException('Could not instantiate service "' . $name . '" because class ' . $class . ' was not found.'); } $instantiateClosure = $this->createInstantiationClosure($class, $service->arguments); // cache this closure $this->instantiateClosuresCache[$name] = $instantiateClosure; // and finally call it return $instantiateClosure(); }
public function testInjectArrayFromParameter() { $container = new Container(); $container->setParameter('names', array('name1', 'name2', 'name3', 'name4')); $container->register('arrayed', array('class' => $this->namedProductClass, 'arguments' => array('%names%'))); $this->assertNotEmpty($container->get('arrayed')); }