Symfony 5 Messenger 不自动配置消息处理程序

Posted

技术标签:

【中文标题】Symfony 5 Messenger 不自动配置消息处理程序【英文标题】:Symfony 5 Messenger not auto configuring message handler 【发布时间】:2020-05-18 01:00:33 【问题描述】:

我是 Symfony 框架的新手,正在尝试使用 Messenger (https://symfony.com/doc/current/messenger.html) 建立一个项目。我的理解是在使用“实现 MessageHandlerInterface”设置处理程序类之后,处理程序应该可以使用,但它似乎对我不起作用。我尝试了几种不同的方法,包括从头开始建立一个新项目。我正在使用 Symfony 5.0.4。

我这样设置项目:

symfony new --full testMessenger
composer require messenger
php bin/console make:controller

然后我创建了一个新的信使和处理程序,并从控制器调用它。这样做我得到了异常:“No handler for message "App\Message\Message".

php bin/console debug:messenger

输出:

Messenger 
========= 

messenger.bus.default 
--------------------- 

The following messages can be dispatched: 

-----------------------------------------------------  
 Symfony\Component\Mailer\Messenger\SendEmailMessage   
     handled by mailer.messenger.message_handler       
 Symfony\Component\Notifier\Message\ChatMessage        
     handled by chatter.messenger.chat_handler         
 Symfony\Component\Notifier\Message\SmsMessage         
     handled by texter.messenger.sms_handler           
-----------------------------------------------------  

我的代码与消息处理程序文档中的示例基本相同,但我将在此处添加。

// src/Message.php
<?php

namespace App\Message;

class Message

    private $content;

    public function __construct(string $content)
    
        $this->content = $content;
    

    public function getContent(): string
    
        return $this->content;
    



// src/MessageHandler.php
<?php

namespace App\MessageHandler;

use App\Message\Message;
use Symfony\Component\Messenger\Handler\MessageHandlerInterface;

class SmsNotificationHandler implements MessageHandlerInterface

    public function __invoke(Message $message)
    
        // ... do some work - like sending an SMS message!
    



// src/Controller/MessageController.php
<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use App\Message\Message;

class MessageController extends AbstractController

    /**
     * @Route("/message", name="message")
     */
    public function index()
    
        $this->dispatchMessage(new Message('Look! I created a message!'));

        return $this->render('message/index.html.twig', [
            'controller_name' => 'MessageController',
        ]);
    





//config/packages/messenger.yaml

    framework:

    messenger:
        # Uncomment this (and the failed transport below) to send failed messages to this transport for later handling.
        # failure_transport: failed

        transports:
            # https://symfony.com/doc/current/messenger.html#transport-configuration
            # async: '%env(MESSENGER_TRANSPORT_DSN)%'
            # failed: 'doctrine://default?queue_name=failed'
            # sync: 'sync://'

        routing:
            # Route your messages to the transports
            # 'App\Message\YourMessage': async

【问题讨论】:

能否也添加 Messenger 配置 @qdequippe 我添加了 config/packages/messenger.yaml 的内容。 谢谢。我看到“// src/MessageHandler.php”但是你的类名是“SmsNotificationHandler”是不是有错别字? @qdequippe 这是一个错字。感谢您指出。这似乎并没有改变任何东西,但我确实弄清楚了它是什么。名称空间必须与目录结构完全匹配。我已将类放在 src 文件夹中,同时保留示例中的名称空间。这很有趣,因为在我遇到这些问题的原始项目中不应该是这种情况。我会仔细检查名称空间问题。 【参考方案1】:

我在类似的情况下有点挣扎,所以我希望这对某人有所帮助:

所以我开启了自动装配,并像这样定义了多个总线:

final class QueryBus implements QueryBusInterface

    use HandleTrait 
        HandleTrait::handle as messengerHandle;
    

    public function __construct(MessageBusInterface $messageBus)
    
        $this->messageBus = $messageBus;
    

    public function handle(object $query): mixed
    
        return $this->messengerHandle($query);
    


final class CommandBus implements CommandBusInterface

    use HandleTrait;

    public function __construct(
        MessageBusInterface $messageBus
    ) 
        $this->messageBus = $messageBus;
    

    public function dispatch(object $command)
    
        return $this->handle($command);
    

// messenger.yaml
framework:
    messenger:

        default_bus: command_bus
        buses:
            command_bus: ~
            query_bus: ~

在发送查询“No handler for message...”时,我遇到了同样的错误

最终帮助的是:

    在 Bus 实现目录中关闭自动装配(通过排除 services.yaml 中的路径。
    App\:
        resource: '../src/'
        exclude:
            - '../src/Bus/'

    手动定义服务:
// services.yaml

services:
    _defaults:
        autowire: true
        autoconfigure: true

    App\src\Bus\CommandBus:
        arguments:
            - '@command_bus'

    App\src\Bus\QueryBus:
        arguments:
            - '@query_bus'

所以实际上它似乎是自动装配问题 - 未能自动装配相同接口(MessageBusInterface)的 2 个实现。缺少服务的实际错误隐藏在 messenger 组件下。

【讨论】:

以上是关于Symfony 5 Messenger 不自动配置消息处理程序的主要内容,如果未能解决你的问题,请参考以下文章

Symfony Messenger:重试延迟不适用于 Redis 传输

Symfony Messenger 不会总是重启

Symfony Messenger / RabbitMQ 中的消费者错误处理

Symfony:我如何在 Messenger 中使用远程过程调用(RPC)?

Symfony messenger 和 mailer:如何添加 binding_key?

如何在 Symfony Messenger 的中间件上禁用日志“信息”?