在Symfony2中访问相对于Bundle的文件

Tho*_*ley 83 php symfony

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

somepage:
    prefix: someprefix
    resource: "@SomeBundle/Resources/config/config.yml"
Run Code Online (Sandbox Code Playgroud)

有没有办法在控制器或其他PHP代码中访问相对于bundle的文件?特别是,我正在尝试使用Symfony\Component\Yaml\Parser对象来解析文件,我不想绝对引用该文件.基本上,我想这样做:

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

我已经检查了Symfony\Component\Finder\Finder类,但我认为这不是我想要的.有任何想法吗?或者我可能完全忽略了这样做的更好方法?

gil*_*den 179

事实上,你可以使用一个服务,即kernel($this->get('kernel')).它有一个叫做的方法locateResource().

例如:

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

  • @ tomtheman5:一定要抓住它的例外情况.如果找不到文件或名称无效,则此方法抛出`\ InvalidArgumentException`,如果名称包含无效/不安全字符,则抛出`\ RuntimeException`. (9认同)
  • 正是我在寻找的!$这个 - >获取( '核心') - > locateResource( "@ SomeBundle /资源/配置/ config.yml"); //完美地工作 (5认同)
  • 愿意给你的不只是+1. (2认同)

faz*_*azy 78

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

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

$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')
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我明白了你的观点,我想到了这一点.但是,问题不在于"加载/执行了什么代码?",而是"MyClass`依赖于什么代码?".当前的`FileLocator`实现使用`KernelInterface`,但如果在将来`MyClass`中发生变化则不需要知道它.而且,现在更清楚的是`MyClass`真正需要什么(并且更少诱惑将它与其他内核功能结合起来).说了这么多,构造函数应该可能需要`Symfony\Component\Config\FileLocatorInterface`而不是`Symfony\Component\HttpKernel\Config\FileLocator`.然后你可以自己写. (9认同)
  • 这是更好的答案 (3认同)

Reu*_*ven 6

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