在Symfony2中访问与捆绑包相关的文件


83

在Symfony2应用程序的路由配置中,我可以引用这样的文件:

somepage:
    prefix: someprefix
    resource: "@SomeBundle/Resources/config/config.yml"

有什么方法可以访问相对于控制器或其他PHP代码中的包的文件?特别是,我尝试使用Symfony \ Component \ Yaml \ Parser对象来解析文件,并且我不想绝对引用该文件。本质上,我想这样做:

$parser = new Parser();
$config = $parser->parse( file_get_contents("@SomeBundle/Resources/config/config.yml") );

我已经签出了Symfony \ Component \ Finder \ Finder类,但是我认为这不是我想要的。有任何想法吗?还是我完全忽略了这样做的更好方法?

Answers:


179

实际上,有一个服务可用于此目的,内核($this->get('kernel'))。它有一种称为的方法locateResource()

例如:

$kernel = $container->getService('kernel');
$path = $kernel->locateResource('@AdmeDemoBundle/path/to/file/Foo.txt');

5
正是我想要的!$ this-> get('kernel')-> locateResource(“ @ SomeBundle / Resources / config / config.yml”); //运作良好
Thomas Kelley

9
@ tomtheman5:确保捕获其异常。\InvalidArgumentException如果找不到文件或名称无效,则抛出此方法,如果\RuntimeException名称包含无效/不安全字符,则抛出。
kgilden 2011年

2
很乐意为您提供不仅仅是+1的服务。
2012年

您将如何(如果有的话)在一个学说的实体中使用该方法(我不认为)将(或应该)访问内核?
Michael.Lumley 2014年

1
@Morslamina查看疯狂的答案。
Tek 2014年

78

Thomas Kelley的答案很好(并且行得通!),但是如果您使用依赖项注入和/或不想将代码直接绑定到内核,则最好使用FileLocator类/服务:

$fileLocator = $container->get('file_locator');
$path = $fileLocator->locate('@MyBundle/path/to/file.txt')

$fileLocator将是的实例\Symfony\Component\HttpKernel\Config\FileLocator$path将是文件的完整绝对路径。

即使file_locator服务本身使用内核,它的依赖性也要小得多(更容易替代您自己的实现,使用测试倍数等)。

要将其与依赖项注入一起使用:

# services.yml

services:
    my_bundle.my_class:
        class: MyNamespace\MyClass
        arguments:
            - @file_locator

# MyClass.php

use Symfony\Component\Config\FileLocatorInterface as FileLocator;

class MyClass
{
    private $fileLocator;

    public function __construct(FileLocator $fileLocator)
    {
        $this->fileLocator = $fileLocator;
    }

    public function myMethod()
    {
        $path = $this->fileLocator->locate('@MyBundle/path/to/file.txt')
    }
}

不错,但是FileLocator注入了KernelInterface,因此,基本上,如果您注入FileLocator而不是Kernel,您做不到任何事情:)
tomazahlin 2014年

10
我明白你的意思,我想到了这一点。但是,问题不是“加载/执行了什么代码?”,而是“MyClass依赖什么代码?”。当前的FileLocator实现使用KernelInterface,但是如果将来发生这种变化,MyClass则无需了解。而且,现在可以更清楚地知道MyClass真正需要什么(并且更少地将其与其他内核功能结合在一起)。说了这么多,构造函数可能应该要求Symfony\Component\Config\FileLocatorInterface而不是Symfony\Component\HttpKernel\Config\FileLocator。然后,您可以编写自己的。
2014年

3
这是更好的答案
NDM 2014年

6

您可以$container->getParameter('kernel.root_dir')用来获取app应用程序的文件夹,并浏览目录至所需的文件。


捆绑包可以在任何目录中。通常的例子:src/Acme/Bundle/MyBundlesrc/Acme/MyBundlevendor/acme/my-bundle/src等。
MariusBalčytis2015年

3

如果要在位于其中的文件中执行此操作,则src/.../SomeBundle/...可以使用__DIR__来获取当前文件的完整路径。然后Resources/...像这样添加您的路径

$foo = __DIR__.'/Resources/config/config.yml';

@ruudy“只有付费计划的注册用户才能完全访问规则说明。此页面显示了通过订阅可以获取的示例。”
prehfeldt

我没有付款,我可以看到完整的描述以及如何解决的解释。也许您只需要注册。
ruudy 2015年

现在我已经注册,我可以看到页面。首先,它说“不应该”而不是“不得”。其次,恕我直言,这仅在您计划将代码发布给公众或计划稍后覆盖资源路径时才重要。在我的封闭源代码项目中不会发生这种情况,因此这对我而言并不重要。如果这一点对您很重要,则取决于要使用它的上下文。不过,感谢您的提示。
prehfeldt 2015年

如果遵循建议,则可以模拟路径,也可以出于测试目的使用它。我不是英语母语人士,最好不要将此php常量用作可能的对象,更不用说在Symfony2之类的框架上使用。
ruudy 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.