【问题标题】:symfony4, Dependency injection, no default argumentsymfony4,依赖注入,无默认参数
【发布时间】:2019-04-12 09:43:07
【问题描述】:

我有这样的控制器功能设置服务

App\Controller\Controller:
    calls:
        - [new, ['@request_stack','@doctrine.orm.default_entity_manager']]

我需要 Entity Manager 在控制器操作中,我的函数看起来像这样

public function new(RequestStack $request, EntityManager $em): Response
{
    $currentRequest = $request->getCurrentRequest();
    $data = json_decode($currentRequest->getContent(), true);
    ....
    return new ApiResponse(['message' => $message['message'], 'body' => 'success']);
}

当执行到return new ApiResponse行时​​,它会出错

Controller "Controller::new()" requires that you provide a value for the "$request" argument. Either the argument is nullable and no null value has been provided, no default value has been provided or because there is a non optional argument after this one.

如何在控制器操作中获取实体管理器或如何解决此问题?

【问题讨论】:

    标签: php symfony dependency-injection


    【解决方案1】:

    正如 Symfony 4 Doc on Doctrine 所说:

    // you can fetch the EntityManager via $this->getDoctrine()
    // or you can add an argument to your action: index(EntityManagerInterface $entityManager)
    $entityManager = $this->getDoctrine()->getManager();
    

    所以您可以通过这种方式在控制器中获取实体管理器

    但是,您也可以将实体管理器注册为服务来使用它。

    请务必将 autowire 设置为 true :

    # config/services.yaml
    services:
        _defaults:
            autowire: true
    

    并将其注册为服务:

       # config/services.yaml
       services:
         #....
            controller_em:
                class: App\Controller\Controller
                arguments: [ '@doctrine.orm.default_entity_manager' ]
                public: true
    

    这样您就可以在控制器中使用它:

    private $objectManager;
    
    public function __construct(ObjectManager $objectManager)
    {
        $this->objectManager = $objectManager;
    
    }
    

    您也可以通过这种方式在 Voter 或 Manager 中使用实体管理器。

    【讨论】:

    • 你没有得到Entity Manager 使用$this->getDoctrine()->getManager() 而是Doctrine\Common\Persistence\ManagerRegistry
    • 我被我的 ide PHPStrom 搞糊涂了,我开始工作了 $this->getDoctrine()->getManager()
    【解决方案2】:

    好吧。你需要将你的东西注入到控制器的对象构造函数中——在 Symfony 中称为 DI(或通过 set-methods):

    services.yml - 如果您的 autowire 一切正常

    App\Controller\Controller:
        calls:
            - [new]
    

    如果不手动添加:

     App\Controller\Controller:
        arguments:
            - '@doctrine.orm.default_entity_manager'
        calls:
            - [new]
    

    控制器.php

    /** @var EntityManager */
    private $em;
    
    public __construct(EntityManager $em)
    {
        $this->em = $em;
    }
    

    然后在你的方法中使用它:

    public function new(RequestStack $request): Response
    {
        $this->em ...
    }
    

    【讨论】:

      【解决方案3】:

      为了您的信息,您可以创建自己的 AbsractController 以将 EntityManager 注入所有像这样扩展它的控制器中。

      <?php
      
      namespace App\Controller;
      
      use Doctrine\ORM\EntityManagerInterface;
      use Symfony\Bundle\FrameworkBundle\Controller\AbstractController as BaseController;
      
      abstract class AbstractController extends BaseController
      {
          /**
           * @var EntityManagerInterface
           */
          protected $em;
      
          /**
           * @required
           *
           * @param EntityManagerInterface $em
           */
          public function setEntityManager(EntityManagerInterface $em)
          {
              $this->em = $em;
          }
      }
      

      如果一个控制器扩展了这个 AbstractController,你可以在其中的任何地方访问 $this->em。

      此处的“必需”注释是启用您尝试执行的操作而无需像您一样添加配置的关键。这就像在您的配置中添加一条呼叫线路!

      您可以为所有控制器中所需的每项服务执行类似的操作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-21
        • 2018-03-23
        • 2023-03-09
        • 2011-10-27
        • 2016-01-26
        • 1970-01-01
        相关资源
        最近更新 更多