symfony4,依赖注入,没有默认参数

时间:2019-04-12 09:43:07

标签: php symfony dependency-injection

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

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.

如何让实体管理者采取控制措施或如何解决此问题?

3 个答案:

答案 0 :(得分:1)

如Symfony 4 Doc on Doc所述:

    CREATE OR REPLACE FUNCTION public.months_back(months_back integer)
     RETURNS timestamp without time zone
     LANGUAGE sql
     IMMUTABLE
    AS $function$
        SELECT cast((date_trunc('month', now()) - (months_back || ' month')::interval)::timestamp AT TIME ZONE current_setting('TimeZone') as timestamp)  
    $function$;

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

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

确保将自动装配设置为true:

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

并将其注册为服务:

# 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

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

答案 1 :(得分:0)

好吧。您需要将您的东西注入控制器的对象构造函数-在Symfony方式中(或通过set-method)称为DI

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

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

如果不手动添加:

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

Controller.php

/** @var EntityManager */
private $em;

public __construct(EntityManager $em)
{
    $this->em = $em;
}

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

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

答案 2 :(得分:0)

为了提供信息,您可以创建自己的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。

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

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