symfony 5.1:如何将控制器定义为服务

symfony 5.1: how to define a controller as a service

说到 Symfony,我有点菜鸟。我正在尝试使用接受服务作为构造函数参数的控制器创建一个包;但是,我收到此错误:

The controller for URI "/heartbeat" is not callable: Controller 
"Acme\HeartbeatBundle\Controller\HeartbeatController" has 
required constructor arguments and does not exist in the container. 
Did you forget to define the controller as a service?

这是Resources/config/services.xml:

<?xml version="1.0" encoding="utf-8"?>
<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
    <services>
        <service id="acme_heartbeat.service.heartbeat_service"
                 class="Acme\HeartbeatBundle\Service\HeartbeatService">
            <argument type="string" id="heartbeat.address"/>
        </service>
        <service id="acme_heartbeat.controller.heartbeat_controller"
                 class="Acme\HeartbeatBundle\Controller\HeartbeatController">
            <argument type="service" id="acme_heartbeat.service.heartbeat_service"/>
            <tag name="controller.service_arguments" />
        </service>
        ...
    </services>
</container>

这是Resources/config/routes.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<routes xmlns="http://symfony.com/schema/routing"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://symfony.com/schema/routing
        https://symfony.com/schema/routing/routing-1.0.xsd">
    <route id="heartbeat" path="/heartbeat" controller="Acme\HeartbeatBundle\Controller\HeartbeatController::heartbeat" methods="GET" />
</routes>

主要的 Symfony 应用 config/routes.yaml:

heartbeat:
    resource: '@AcmeHeartbeatBundle/Resources/config/routes.xml'

Controller/HeartbeatController.php:

<?php

declare(strict_types=1);

namespace Acme\HeartbeatBundle\Controller;

use Acme\HeartbeatBundle\Service\HeartbeatService;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

class HeartbeatController extends AbstractController
{
    public function __construct(HeartbeatService $hbs)
    {
        ...
    }

    ...
}

这是Service/HeartbeatService.php:

<?php

namespace Acme\HeartbeatBundle\Service;

class HeartbeatService
{
    ...
}

有人能告诉我我做错了什么吗?

从 Symfony 4 开始,首选的服务命名方式是 use the FQCN as the service id in order to ease autowiring。您使用了 old-style 字符串 ID,因此即使 class 匹配,当 Symfony 按预期 ID 查找它时,它也找不到它。

这很容易解决,要么将定义更改为

<service id="Acme\HeartbeatBundle\Controller\HeartbeatController">

或添加别名:

<service id="Acme\HeartbeatBundle\Controller\HeartbeatController" 
         alias="acme_heartbeat.controller.heartbeat_controller" />

您也可以将路由定义更改为已注册的服务 ID (acme_heartbeat.controller.heartbeat_controller::index),但我会遵循建议并选择第一个选项。