我不确定在这里找到任何解决方案,因为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())
)。