【问题标题】:Accessing Files Relative to Bundle in Symfony2在 Symfony2 中访问与 Bundle 相关的文件
【发布时间】: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 类,但我认为这不是我想要的。有任何想法吗?或者也许我完全忽略了这样做的更好方法?

【问题讨论】:

    标签: php symfony


    【解决方案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 这样的框架了。
    猜你喜欢
    • 2011-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-01
    • 2014-11-15
    • 2012-10-07
    相关资源
    最近更新 更多