Symfonyでwebアプリケーションを開発するのに必須といっても過言ではないJMSDIExtraBundle。
しかし、JMSDIExraBundleを有効にしてからwebからアクセスすると、コントローラのアクションの中で$this->get("service_name")
みたいなコードでエラーになりました。
Symfony2系だと特に問題ないのですが、Symfony3.3でJMSDiExtraBundleを導入したところ、ControllerクラスにDIコンテナがinjectされなくなりました。
何が原因なのか?
JMSDiExtraBundleを有効にするとControllerResolverクラスがJMSDiExtraBundleのものに差し替わります。
https://git.io/v5ruv
JMSDiExtraBundleのControllerResolverクラスでは、DIコンテナにすでに対象のコントローラが登録されていたら、DIコンテナからコントローラを取り出します。
そしてSymfony3.3だとapp/config/services.yml
でControllerクラスがDI登録されているんですよね。デフォルトで・・・
|
|
この時app/config/services.yml
では特にContainerをInjectする設定をしていません。
だからcontainerがないとエラーが発生しているようです。
ということで、services.ymlでコントローラのDI登録をやめれば正常に動くようです。
どこでControllerResolverクラスが差し替わっているのか?
なぜJMSDiExtraBundleをAppKernelに登録するとControllerResolverクラスが差し替わるのか?ちょっと気になったのでついでに調べてみました。
どうやらJMS\DiExtraBundle\DependencyInjection\Compiler\IntegrationPass
クラスでJMSDiExtraBundleのControllerResolverに差し替えているようです。
https://git.io/v5rzr
じゃあIntegrationPass
はどこでコンテナに登録されるかというとJMS\DiExtraBundle\JMSDiExtraBundle
クラスで登録されています。
https://git.io/v5rgO
つまりAppKernelにJMSDiExtraBundleを登録したらControllerResolverが差し替わるということですね。
どう対応するのがベストなのか?
Controllerクラスを継承しない、そしてContainerをControllerから使わないという方法がベストなのかと思います。
Controllerが必要なものはDIでInjectするのがいいかと。
最後に
Symfony3系では、DI登録が柔軟にできるようになりました。(app/config/services.ymlを見ればわかると思います)
JMSDiExtraBundleが本当に必要なのか?導入するメリットは本当にあるのか?
今一度考え直してみるのも良いかもしれません。