3

I'm not sure to find any solution here, as this similar question as already been asked but give a (working) solution that I can't implement, because I'm working on the symfony FrameworkBundle (for a bugfix).

Situation

In a compiler pass (or a bundle extension), I need to get the path to load resources of each bundle of the application (3rd party included, all bundles registered in the Kernel).

For now, I use the following in a bundle extension where the ContainerBuilder is accessible:

foreach ($container->getParameter('kernel.bundles') as $bundle) {
    // Create a reflection from the FQCN of the bundle class
    $reflection = new \ReflectionClass($bundle);
    // Localise the file containing the class
    $path = dirname($reflection->getFilename());

    // Do stuffs that load files such as $path/Resources/config/serializer.yml
}

Every bundle class has a getPath() method that can return a custom path in case of custom directory structure.

So, use the reflection file could lead to ignore some configuration files instead of load them properly.

Wrong alternative

Create an instance of the bundle and invoke the getPath() method, could be:

$reflection = new \ReflectionClass($bundle);
$getPathReflection = new \ReflectionMethod($bundle, 'getPath');
$path = $getPathReflection->invoke(new $bundle());

But what about if one of the bundle classes take one (or more) constructor arguments?
This would lead to a fatal error.

Problem

So, I can't create the instances manually because I don't have the knowledge of what they need to be instantiated.

My first thought was that I can get the kernel service then loop over $kernel->getBundles() and call the getPath() method.

But the result of $container->get('kernel') is:

[Symfony\Component\DependencyInjection\Exception\RuntimeException]
You have requested a synthetic service ("kernel"). The DIC does not know how to construct this service.

Is there a way to call this method for each bundle class in a compiler pass/bundle extension without adding an argument to the FrameworkBundle class?

EDIT

First possible alternative:

$getPathReflection = new \ReflectionMethod($bundle, 'getPath');
$reflectionInstance = $reflection->newInstanceWithoutConstructor();
$path = $getPathReflection->invoke($reflectionInstance) ?: dirname($reflection->getFilename());

cons:

  • \ReflectionClass::newInstanceWithoutConstructor() is available since PHP 5.4 only, so the tests don't pass.
  • In case of the Bundle#getPath() value depends on constructor arguments, this would leads to null, and so to use the reflection path (i.e. ?: dirname($reflection->getFilename())).
Community
  • 1
  • 1
chalasr
  • 12,971
  • 4
  • 40
  • 82

0 Answers0