从编译器传递中检索bundle类实例

时间:2016-04-19 09:40:14

标签: php symfony

我不确定在这里找到任何解决方案,因为this similar question已经被问过,但提供了一个我无法实现的(工作)解决方案,因为我正在研究symfony {{3} (对于FrameworkBundle)。

场合

在编译器传递(或扩展包)中,我需要获取加载应用程序的每个包的资源的路径(包括第三方,在内核中注册的所有包)。

目前,我在可以访问ContainerBuilder的bundle扩展中使用以下内容:

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
}

每个bundle类都有一个getPath()方法,可以在自定义目录结构的情况下返回自定义路径。

因此,使用反射文件可能会导致忽略某些配置文件而不是正确加载它们。

错误的替代

创建捆绑包的实例并调用getPath()方法,可以是:

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

但是,如果其中一个bundle类采用一个(或多个)构造函数参数呢? 这会导致致命的错误。

问题

所以,我不能手动创建实例,因为我不知道他们需要实例化什么。

我的第一个想法是,我可以获得kernel服务然后循环$kernel->getBundles()并调用getPath()方法。

$container->get('kernel')的结果是:

  

[Symfony的\元器件\ DependencyInjection \异常\的RuntimeException]
  您已请求合成服务(“内核”)。 DIC不知道如何构建此服务。

有没有办法在编译器传递/包扩展中为每个bundle类调用此方法而不向FrameworkBundle类添加参数?

修改

第一种可能的选择:

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

缺点:

  • \ReflectionClass::newInstanceWithoutConstructor()仅适用于PHP 5.4,因此测试无法通过。
  • 如果Bundle#getPath()值取决于构造函数参数,则会导致null,因此要使用反射路径(即?: dirname($reflection->getFilename()))。

0 个答案:

没有答案