/** * Resolves a service definition into the actual service object. * * @param Service $service Service definition. * @return object */ public function resolve(Service $service) { // if already instantiated then just return that instance if ($service->isSingleton() && ($instance = $service->getInstance())) { return $instance; } // cannot resolve an abstract service if ($service->abstract) { throw new AbstractServiceException('Could not instantiate abstract service "' . $service->name . '".'); } // if the service is extending any other service then resolve all parent definitions $service = $this->resolveHierarchy($service); $instance = $this->instantiateService($service); // setting the instance already here will help circular reference via setter injection working // but only for singleton services // $service now might be a clone because of `::resolveHierarchy()` and therefore this instance // reference would be lost - so let's get the original definition and update it if ($service->isSingleton() && $service->isExtending()) { $originalService = $this->container->getDefinition($service->getName()); $originalService->setSingleton(true); $originalService->setInstance($instance); } else { $service->setInstance($instance); } // if there are any method calls, then call them try { foreach ($service->methodCalls as $call) { $this->callMethod($service, $call['method'], $call['arguments'], $instance); } } catch (CircularReferenceException $e) { throw $e; } catch (Exception $e) { throw new InvalidServiceException('Could not instantiate service "' . $service->name . '" because one of its method calls could not be resolved: ' . $e->getMessage(), 0, $e); } return $instance; }