symfony2での自定義クラス内でのコンテナ取得方法

1,441 views
Skip to first unread message

shuogawa

unread,
Feb 16, 2011, 11:15:44 PM2/16/11
to 日本Symfonyユーザー会
こんにちは。はじめて投稿させて頂きます。

symfony2はDependencyInjectionにて作成された
containerから必要なリソースを取得し
アプリケーションを構築する流れだと思います。

そのコンテナの取得方法ですが、
symfony2内部のコードは
オブジェクト内部にcontainerまたはkernelの参照があったり、
Controllerの様にContainerAwareを継承し、
容易にコンテナを取得出来るようになっておりますが、

自分で作成したクラス内で
コンテナをどの様に取得するかが分かりません。

簡単なコードですが、サンプルです。
<?php
namespace MyNameSpace;
class MyClass{
public function test(){
//ここでコンテナを取得したいが、取得方法が分からない
$container = null;
}
}

もしかしたら、
コンテナの取得に困る事自体が設計ミスかとも思うのですが、
コンテナを取得する良い方法があれば教えて頂ければと思います。

よろしくお願いします。

小川 修
shuo...@gmail.com

hidenorigoto

unread,
Feb 16, 2011, 11:35:02 PM2/16/11
to symfony-...@googlegroups.com
後藤です


この「コンテナを自クラス内で扱えるようにする」方法ですが、いくつかあります。
・コンテナオブジェクトを持っている別オブジェクトからsetContainerのようなメソッドでセットする
・自クラスをコンテナ経由でロードし、その時にコンストラクタまたはsetContainer等のメソッド経由でコンテナ自身を自動injectする

利用したい場面をもう少し詳しくご説明いただくと、その方向に合わせて回答しやすいかもしれませんが、上に挙げた
後者の方法の場合、自作のバンドルにDIコンテナ用のサービス定義XMLを記述して、エクステンションのロードして
XMLを読み込ませてDIコンテナにサービスとして組み込むような流れかと思います。

コア部分だと、コンストラクタでinjectしているものがほとんどですね。



# これだ、という解説ページがないですね・・・。
# 誰かが解説エントリを書いてくれるんじゃないかと期待

hidenorigoto

unread,
Feb 17, 2011, 2:35:05 AM2/17/11
to symfony-...@googlegroups.com
後藤です

こちらのご質問の件ですが、簡単なサンプルをgistへ上げました


この例だと、コンストラクタでinjectしています。


shuogawa

unread,
Feb 18, 2011, 1:07:32 AM2/18/11
to 日本Symfonyユーザー会
後藤さん、ありがとうございました。

自分でsetContainer()等をコールしてセットする
または
DI経由でセットする
の二つが基本という事ですね。

ただ、

doctrine2 orm の entityクラスなど、
インスタンス化が自動化されているクラスへの
コンテナの設定は何か良い方法はあるでしょうか?

doctrine2のeventを利用しコンテナをセットする方法もあるかと思いますが、
その方法ではコンテナを利用するだけなのに敷居が高すぎる気がします。

何かよい方法がございましたら、ご教授頂ければと思います。

小川

hidenorigoto

unread,
Feb 18, 2011, 3:59:00 AM2/18/11
to symfony-...@googlegroups.com
後藤です


なるほど、Entityクラスから使いたいということですね。
これは確かに現状ではめんどくさそうで、小川さんも書いていらっしゃるように
イベントなどを使わないとできないように思います。
(私自身、まださほど理解が深まっておらず、もしかすると他に良い方法はあるかもしれません)

新しくインスタンスを作る側ならいくらでもやりようがあるんでしょうけど、findメソッド等で
暗黙的にインスタンス化される場合のフック箇所が、現状では少なそうなんですよね。

Entityにcontainerを手軽に注入するビヘイビアのようなものは、あってもよいなとは思いますので、
実装は考えてはみます。



shuogawa

unread,
Feb 18, 2011, 11:12:46 PM2/18/11
to 日本Symfonyユーザー会
こんにちは小川です。
ご返信ありがとうございます。

正式リリースももう少しですし、
今後ノウハウもたまってくると思いますので、

現状では

kernelへの参照をstaticクラスに代入し、
切りぬける事としました。

AppKernelにて
boot()関数をオーバーライドしてます

良いコードかは不明ですが、ご参考までに。

<?php
class AppKernel extends Kernel
{
public function boot(){
   parent::boot();
\MyStaticClass::$kernel = $this;
}
}

<?php
class MyClass
{
public function foo(){
   $container = \MyStaticClass::$kernel->getContainer();

hidenorigoto

unread,
Feb 19, 2011, 5:24:20 AM2/19/11
to symfony-...@googlegroups.com
後藤です


AppKernelからkernelインスタンスをセットするようにされたんですね。

もしこのスタティックなクラス等も含めて単一のバンドルで完結する場合は、バンドルクラスのboot()メソッド内
で記述する方がよいかもしれません。
この場合、kernelの参照ではなくて、containerの参照になりますが・・・。

class HelloBundle extends Bundle
{
    public function boot()
    {
        parent::boot(); 
        \MyStaticClass::$container = $this->container; 
    }
}

ほぼ同じような内容ですが、こちらに書いておけば(コードとしては)バンドル内に閉じ込められます。

Reply all
Reply to author
Forward
0 new messages