在 Symfony2 中访问与 Bundle 相关的文件

Posted

技术标签:

【中文标题】在 Symfony2 中访问与 Bundle 相关的文件【英文标题】:Accessing Files Relative to Bundle in Symfony2 【发布时间】:2011-11-26 23:32:05 【问题描述】:

在 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 类,但我认为这不是我想要的。有任何想法吗?或者也许我完全忽略了这样做的更好方法?

【问题讨论】:

【参考方案1】:

事实上,您可以使用一个服务,即内核 ($this->get('kernel'))。它有一个名为locateResource() 的方法。

例如:

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

【讨论】:

正是我想要的! $this->get('kernel')->locateResource("@SomeBundle/Resources/config/config.yml"); // 完美运行 @tomtheman5:一定要捕获它的异常。如果找不到文件或名称无效,则此方法抛出\InvalidArgumentException,如果名称包含无效/不安全字符,则抛出\RuntimeException 愿意为您提供的不仅仅是 +1。 您将如何(如果有的话)在一个(我不认为)会(或应该)访问内核的学说实体中使用此方法? @Morslamina 查看 fazy 的回答。【参考方案2】:

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,你不会做的更好:) 我明白你的意思,我想到了这一点。但是,问题不是“加载/执行了什么代码?”,而是“MyClass 依赖什么代码?”。当前的FileLocator 实现使用KernelInterface,但如果将来发生变化MyClass 不需要知道它。此外,现在更清楚MyClass 真正需要什么(并且减少了将其与其他内核功能结合起来的诱惑)。说了这么多,构造函数应该可能需要Symfony\Component\Config\FileLocatorInterface 而不是Symfony\Component\HttpKernel\Config\FileLocator。然后你就可以自己写了。 这是更好的答案【参考方案3】:

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

【讨论】:

Bundle 可以在任何目录中。常用示例:src/Acme/Bundle/MyBundlesrc/Acme/MyBundlevendor/acme/my-bundle/src 等。【参考方案4】:

如果您想在位于src/.../SomeBundle/... 的文件中执行此操作,您可以使用__DIR__ 获取当前文件的完整路径。然后将您的 Resources/... 路径附加到类似

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

【讨论】:

@ruudy “只有拥有付费计划的注册用户才能获得对规则描述的完全访问权限。此页面显示了通过订阅可以获得的示例。” 我没有付款,我可以看到完整的描述和如何解决它的解释。也许你只需要注册。 现在我已经注册了,我可以看到页面了。首先,它说“不应该”而不是“不得”。其次,恕我直言,这仅在您计划向公众发布代码或计划稍后覆盖资源路径时才重要。在我的闭源项目中,这不会发生,所以这对我来说并不重要。这取决于您将要使用它的上下文,如果这一点对您很重要。不过感谢您的提示。 如果您遵循建议,您可以模拟路径,或者出于测试目的使用它。我不是英语本地人,最好不要尽可能使用这个 php 常量,更不用说像 Symfony2 这样的框架了。

以上是关于在 Symfony2 中访问与 Bundle 相关的文件的主要内容,如果未能解决你的问题,请参考以下文章

Payum Bundle:如何在 symfony2 中更改捕获操作的视图

Symfony2 KnpPaginator bundle 从多个实体获取数据并在一个网格/分页中呈现

Symfony2:列出虚拟文件夹(Netbeans)中的所有视图/路由文件

Symfony2 Sonata Media Bundle 自定义图像裁剪

在将 RabbitMQ Bundle 用于 Symfony2 时防止在 RabbitMQ 中创建多个连接

Symfony2 Doctrine ORM 安装配置