Symfony3控制器构造函数注入不起作用

时间:2017-01-21 12:55:20

标签: php symfony

我想使用以下代码将EntityManager实例传递给控制器​​的构造函数:

namespace AppBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Doctrine\ORM\EntityManager;

class UserController extends Controller
{

    public function __construct( EntityManager $entityManager )
    {
        // do some stuff with the entityManager
    }
}

我通过将参数放入service.yml文件来执行构造函数注入:

parameters:
#    parameter_name: value

services:
#    service_name:
#        class: AppBundle\Directory\ClassName
#        arguments: ["@another_service_name", "plain_value", "%parameter_name%"]
    app.user_controller:
        class: AppBundle\Controller\UserController
        arguments: ['@doctrine.orm.entity_manager']

service.yml包含在config.yml中,当我运行

  

php bin / console debug:container app.user_controller

我明白了:

 Information for Service "app.user_controller"
 =============================================

 ------------------ ------------------------------------- 
  Option             Value                                
 ------------------ ------------------------------------- 
  Service ID         app.user_controller                  
  Class              AppBundle\Controller\UserController  
  Tags               -                                    
  Public             yes                                  
  Synthetic          no                                   
  Lazy               no                                   
  Shared             yes                                  
  Abstract           no                                   
  Autowired          no                                   
  Autowiring Types   -                                    
 ------------------ ------------------------------------- 

但是,调用映射到我的控制器的路由,我得到:

  

UserController.php第17行中的FatalThrowableError:输入错误:   争论1传递给   AppBundle \ Controller \ UserController :: __ construct()必须是一个实例   Doctrine \ ORM \ EntityManager,没有给出,调用   /home/michel/Documents/Terminfinder/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php   在第202行

我无法弄清楚,为什么EntityManager没有被注入?

4 个答案:

答案 0 :(得分:4)

使用基类Controller.php时,Container的框架通常会自动连接 public function listUsers(Request $request) { $em = $this->container->get('doctrine.orm.entity_manager'); }

基本上你是在试图混淆事情的实际效果。

要解决您的问题,您基本上有两个解决方案:

  1. 不要尝试注入依赖项,而是直接从您的action / method中的Container中获取它。
  2. Controller

    1. 手动创建控制器但不扩展Controller基类;和ControllerResolver
    2. 为了进一步了解这一点,有些人会建议不要使用Symfony提供的默认控制器。

      虽然我完全理解他们的观点,但我对这个主题的态度稍微有点了。

      仅注入所需依赖关系背后的想法是避免并迫使人们拥有瘦控制器, 是一件好事。

      但是,通过一些自动确定,使用现有的快捷方式要简单得多。

      Action / Views只不过是您DomainModels / Controller之间的粘合剂。

      使用ContainerAware工具阻止自己在Controller中做太多事情。

      如果您的系统中没有生成业务更改,则{{1}}可能会被丢弃。

答案 1 :(得分:1)

自2017年起和Symfony 3.3 + ,对控制器的本地支持即服务。

您可以保持控制器的运行方式,因为正确使用构造函数注入

只需修改您的services.yml

即可
# app/config/services.yml

services:
    _defaults:
        autowire: true

    AppBundle\:
        resouces: ../../src/AppBundle

它会:

  • 将所有控制器和存储库加载为服务
  • autowire构造函数依赖项(在您的情况下为EntityManager


进一步:存储库作为服务

关于 Doctrine +存储库+服务+控制器的问题很多,所以我放下了一个general answer to a post 。 Definitelly检查您是否更喜欢构造函数注入和服务而不是静态和服务定位器。

答案 2 :(得分:-1)

您是否使用以下模式来呼叫控制器AppBundle:Default:index?如果是的那应该是问题。如果要将控制器用作服务,则必须使用模式:app.controller_id:indexAction,它使用服务的id加载控制器。

否则,它将尝试在不使用服务容器的情况下创建类的实例。

有关详细信息,请参阅有关此主题{0}}

的symfony文档

答案 3 :(得分:-4)

实体管理器在控制器中可用,无需注入它。所需要的只是:

$em = $this->getDoctrine()->getManager();