Closed
Description
Symfony version(s) affected
7.2.0
Description
The ContainerBuilder::getReflectionClass() method does not support interfaces when 'symfony/config' package not present.
Given an interface MyInterface
..
With symfony/config package present, $builder->getReflectionClass(MyInterface::class)
will return a \ReflectionClass
object for that interface.
With symfony/config package missing, $builder->getReflectionClass(MyInterface::class)
will return false
.
This has an impact on AutowirePass
, if the class on a service definition is an interface.
How to reproduce
This problem manifests in two levels.
Low-level manifestation
<?php
use Symfony\Component\DependencyInjection\ContainerBuilder;
require_once __DIR__ . '/vendor/autoload.php';
interface I {}
$rc = (new ContainerBuilder())->getReflectionClass(I::class);
// With symfony/config: ReflectionClass.
// Without symfony/config: NULL
print get_debug_type($rc) . "\n";
Higher level manifestation in autowire
<?php
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
require_once __DIR__ . '/vendor/autoload.php';
class Dependency {}
interface ServiceInterface {}
class Service implements ServiceInterface {}
class Factories {
public static function createService(
Dependency $dependency,
): ServiceInterface {
return new Service();
}
}
$builder = new ContainerBuilder();
$definition = new Definition(Dependency::class);
$builder->setDefinition(Dependency::class, $definition);
$definition = new Definition(ServiceInterface::class);
$definition->setAutowired(true);
$definition->setFactory([Factories::class, 'createService']);
$definition->setPublic(true);
$builder->setDefinition('service', $definition);
$builder->compile();
$service = $builder->get('service');
print get_debug_type($service) . "\n";
Possible Solution
In ContainerBuilder::getReflectionClass(), add a
|| interface_exists($class)`.
try {
if (isset($this->classReflectors[$class])) {
$classReflector = $this->classReflectors[$class];
} elseif (false && class_exists(ClassExistenceResource::class)) {
$resource = new ClassExistenceResource($class, false);
$classReflector = $resource->isFresh(0) ? false : new \ReflectionClass($class);
} else {
$classReflector = (class_exists($class) || interface_exists($class)) ? new \ReflectionClass($class) : false;
}
} catch (\ReflectionException $e) {
if ($throw) {
throw $e;
}
}
Additional Context
No response