Skip to main content
Drupal API
User account menu
  • Log in

Breadcrumb

  1. Drupal Core 11.1.x
  2. ContainerBuilder.php

function ContainerBuilder::createService

Creates a service for a service definition.

Throws

RuntimeException When the factory definition is incomplete

RuntimeException When the service is a synthetic service

InvalidArgumentException When configure callable is not callable

2 calls to ContainerBuilder::createService()
ContainerBuilder::doGet in vendor/symfony/dependency-injection/ContainerBuilder.php
ContainerBuilder::doResolveServices in vendor/symfony/dependency-injection/ContainerBuilder.php

File

vendor/symfony/dependency-injection/ContainerBuilder.php, line 1082

Class

ContainerBuilder
ContainerBuilder is a DI container that provides an API to easily describe services.

Namespace

Symfony\Component\DependencyInjection

Code

private function createService(Definition $definition, array &$inlineServices, bool $isConstructorArgument = false, ?string $id = null, bool|object $tryProxy = true) : mixed {
    if (null === $id && isset($inlineServices[$h = spl_object_hash($definition)])) {
        return $inlineServices[$h];
    }
    if ($definition instanceof ChildDefinition) {
        throw new RuntimeException(\sprintf('Constructing service "%s" from a parent definition is not supported at build time.', $id));
    }
    if ($definition->isSynthetic()) {
        throw new RuntimeException(\sprintf('You have requested a synthetic service ("%s"). The DIC does not know how to construct this service.', $id));
    }
    if ($definition->isDeprecated()) {
        $deprecation = $definition->getDeprecation($id);
        trigger_deprecation($deprecation['package'], $deprecation['version'], $deprecation['message']);
    }
    $parameterBag = $this->getParameterBag();
    $class = $parameterBag->resolveValue($definition->getClass()) ?: ([
        'Closure',
        'fromCallable',
    ] === $definition->getFactory() ? 'Closure' : null);
    if ([
        'Closure',
        'fromCallable',
    ] === $definition->getFactory() && ('Closure' !== $class || $definition->isLazy())) {
        $callable = $parameterBag->unescapeValue($parameterBag->resolveValue($definition->getArgument(0)));
        if ($callable instanceof Reference || $callable instanceof Definition) {
            $callable = [
                $callable,
                '__invoke',
            ];
        }
        if (\is_array($callable) && ($callable[0] instanceof Reference || $callable[0] instanceof Definition && !isset($inlineServices[spl_object_hash($callable[0])]))) {
            $initializer = function () use ($callable, &$inlineServices) {
                return $this->doResolveServices($callable[0], $inlineServices);
            };
            $proxy = eval('return ' . LazyClosure::getCode('$initializer', $callable, $definition, $this, $id) . ';');
            $this->shareService($definition, $proxy, $id, $inlineServices);
            return $proxy;
        }
    }
    if (true === $tryProxy && $definition->isLazy() && [
        'Closure',
        'fromCallable',
    ] !== $definition->getFactory() && !($tryProxy = !($proxy = $this->proxyInstantiator ??= new LazyServiceInstantiator()) || $proxy instanceof RealServiceInstantiator)) {
        $proxy = $proxy->instantiateProxy($this, (clone $definition)->setClass($class)
            ->setTags(($definition->hasTag('proxy') ? [
            'proxy' => $parameterBag->resolveValue($definition->getTag('proxy')),
        ] : []) + $definition->getTags()), $id, function ($proxy = false) use ($definition, &$inlineServices, $id) {
            return $this->createService($definition, $inlineServices, true, $id, $proxy);
        });
        $this->shareService($definition, $proxy, $id, $inlineServices);
        return $proxy;
    }
    if (null !== $definition->getFile()) {
        require_once $parameterBag->resolveValue($definition->getFile());
    }
    $arguments = $definition->getArguments();
    if (null !== ($factory = $definition->getFactory())) {
        if (\is_array($factory)) {
            $factory = [
                $this->doResolveServices($parameterBag->resolveValue($factory[0]), $inlineServices, $isConstructorArgument),
                $factory[1],
            ];
        }
        elseif (!\is_string($factory)) {
            throw new RuntimeException(\sprintf('Cannot create service "%s" because of invalid factory.', $id));
        }
        elseif (str_starts_with($factory, '@=')) {
            $factory = fn(ServiceLocator $arguments) => $this->getExpressionLanguage()
                ->evaluate(substr($factory, 2), [
                'container' => $this,
                'args' => $arguments,
            ]);
            $arguments = [
                new ServiceLocatorArgument($arguments),
            ];
        }
    }
    $arguments = $this->doResolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($arguments)), $inlineServices, $isConstructorArgument);
    if (null !== $id && $definition->isShared() && (isset($this->services[$id]) || isset($this->privates[$id])) && (true === $tryProxy || !$definition->isLazy())) {
        return $this->services[$id] ?? $this->privates[$id];
    }
    if (!array_is_list($arguments)) {
        $arguments = array_combine(array_map(fn($k) => preg_replace('/^.*\\$/', '', $k), array_keys($arguments)), $arguments);
    }
    if (null !== $factory) {
        $service = $factory(...$arguments);
        if (!$definition->isDeprecated() && \is_array($factory) && \is_string($factory[0])) {
            $r = new \ReflectionClass($factory[0]);
            if (0 < strpos($r->getDocComment(), "\n * @deprecated ")) {
                trigger_deprecation('', '', 'The "%s" service relies on the deprecated "%s" factory class. It should either be deprecated or its factory upgraded.', $id, $r->name);
            }
        }
    }
    else {
        $r = new \ReflectionClass($class);
        if (\is_object($tryProxy)) {
            if ($r->getConstructor()) {
                $tryProxy->__construct(...$arguments);
            }
            $service = $tryProxy;
        }
        else {
            $service = $r->getConstructor() ? $r->newInstanceArgs($arguments) : $r->newInstance();
        }
        if (!$definition->isDeprecated() && 0 < strpos($r->getDocComment(), "\n * @deprecated ")) {
            trigger_deprecation('', '', 'The "%s" service relies on the deprecated "%s" class. It should either be deprecated or its implementation upgraded.', $id, $r->name);
        }
    }
    $lastWitherIndex = null;
    foreach ($definition->getMethodCalls() as $k => $call) {
        if ($call[2] ?? false) {
            $lastWitherIndex = $k;
        }
    }
    if (null === $lastWitherIndex && (true === $tryProxy || !$definition->isLazy())) {
        // share only if proxying failed, or if not a proxy, and if no withers are found
        $this->shareService($definition, $service, $id, $inlineServices);
    }
    $properties = $this->doResolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getProperties())), $inlineServices);
    foreach ($properties as $name => $value) {
        $service->{$name} = $value;
    }
    foreach ($definition->getMethodCalls() as $k => $call) {
        $service = $this->callMethod($service, $call, $inlineServices);
        if ($lastWitherIndex === $k && (true === $tryProxy || !$definition->isLazy())) {
            // share only if proxying failed, or if not a proxy, and this is the last wither
            $this->shareService($definition, $service, $id, $inlineServices);
        }
    }
    if ($callable = $definition->getConfigurator()) {
        if (\is_array($callable)) {
            $callable[0] = $parameterBag->resolveValue($callable[0]);
            if ($callable[0] instanceof Reference) {
                $callable[0] = $this->doGet((string) $callable[0], $callable[0]->getInvalidBehavior(), $inlineServices);
            }
            elseif ($callable[0] instanceof Definition) {
                $callable[0] = $this->createService($callable[0], $inlineServices);
            }
        }
        if (!\is_callable($callable)) {
            throw new InvalidArgumentException(\sprintf('The configure callable for class "%s" is not a callable.', get_debug_type($service)));
        }
        $callable($service);
    }
    return $service;
}

API Navigation

  • Drupal Core 11.1.x
  • Topics
  • Classes
  • Functions
  • Constants
  • Globals
  • Files
  • Namespaces
  • Deprecated
  • Services
RSS feed
Powered by Drupal