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クラスをチェックアウトしましたが、それが私が探しているものではないと思います。何か案は?それとも、これを行うためのより良い方法を見落としているのでしょうか?

回答:


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 2011

9
@ tomtheman5:必ずその例外をキャッチしてください。このメソッドは\InvalidArgumentException、ファイルが見つからない\RuntimeExceptionか名前が無効な場合、および名前に無効/安全でない文字が含まれている場合にをスローします。
kgilden 2011

2
+1以上のものを提供したいと思います。
インフルエンザ

カーネルにアクセスできる(またはすべきである)教義エンティティ内でこのメソッドをどのように(もしあれば)使用しますか?
Michael.Lumley 2014

1
@Morslaminafazyの答えをチェックしてください。
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を注入するので、基本的に、Kernelの代わりにFileLocatorを注入した場合、何も改善されません:)
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およびにそう。
マリウスBalčytis

3

にあるファイルでこれを実行するsrc/.../SomeBundle/...場合は、を使用__DIR__して現在のファイルのフルパスを取得できます。次にResources/...、そのようなものにパスを追加します

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

@ruudy「有料プランの登録ユーザーのみがルールの説明に完全にアクセスできます。このページには、サブスクライブすることで取得できるもののサンプルが表示されます。」
prehfeldt 2015

私は支払いをしませんでした、そして私はそれを解決する方法の完全な説明と説明を見ることができます。たぶんあなたは登録する必要があるだけです。
ruudy 2015

登録したので、ページを見ることができます。まず第一に、それは「すべきではない」と「してはいけない」と言っています。次に、これは、コードを一般に公開する予定がある場合、または後でリソースパスをオーバーライドする予定がある場合にのみ重要です。私のクローズドソースプロジェクトではこれは起こらないので、これは私にとってそれほど重要ではありません。この点があなたにとって重要であるかどうかは、それを使用するコンテキストによって異なります。それにもかかわらず、ヒントをありがとう。
prehfeldt 2015

推奨事項に従えば、パスをモックするか、テスト目的でそれを試すことができます。私は英語を母国語とはしていません。Symfony2のようなフレームワークでは、このphp定数を可能な限り使用しない方がよいでしょう。
ruudy 2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.