Symfony消息处理器是标记为#[AsMessageHandler]并实现__invoke()方法的类,参数类型须与消息类完全一致;路由配置必须精确匹配消息类全名,而非处理器类名。
写 Symfony 消息
处理器
,核心是定义一个能被自动识别、接收特定消息并执行业务逻辑的类。它不处理传输或调度,只专注“收到这个消息后我该做什么”。关键不在复杂度,而在职责清晰和配置精准。
消息处理器的基本写法
处理器本质是一个 PHP 类,必须满足两个条件:标记为处理器、实现可调用接口。
使用
属性标记(推荐,Symfony 6.2+ 默认方式)
类中定义
方法,参数类型必须与你要处理的消息类完全一致
消息类本身需是简单数据载体,不可含 Doctrine 实体、闭包、资源句柄等不可序列化内容
示例:
依赖注入与业务协作
处理器不是孤岛,常需调用其他服务完成工作。Symfony 支持完整构造函数注入,无需手动获取容器。
vue.js + axios.js图片压缩处理并上传到服务器
vue.js + axios.js图片压缩处理并上传到服务器
下载
在
中声明所需服务(如
、
)
避免在
内部用
,破坏可测试性
若需条件执行(如仅生产环境发邮件),应通过配置或策略类解耦,而非硬编码判断环境
路由配置必须精确匹配
处理器写好了,但没被调用?90% 是路由配错了。Messenger 不按命名空间前缀或 handler 名匹配,而是严格比对
你 dispatch 时 new 出的那个类的完整类名
。
正确写法(在
中):
错误写法:
(这是 handler 类,不是 message 类)
(通配符不生效)
类名大小写、反斜杠、命名空间缺一不可;建议用 IDE 的 “Go to Class” 确认路径
异步消费与调试要点
处理器只负责处理,不负责启动消费者。要真正触发异步执行,还需两步:
确保传输已就绪:
输出 “Transport 'async' is ready!”
手动运行消费者:
(加
防止无限运行)
调试时可用
查看路由是否生效、handler 是否注册成功
#[AsMessageHandler]__invoke()namespace App\MessageHandler;
use App\Message\SendWelcomeEmail;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
#[AsMessageHandler]
class SendWelcomeEmailHandler
{
public function __invoke(SendWelcomeEmail $message)
{
// 从 $message->getUserId() 获取 ID,查用户,发邮件
// 不在这里 new EntityManager 或直接 echo,保持专注
}
}__construct()MailerInterfaceEntityManagerInterface__invoke()$this->container->get()config/packages/messenger.yamlApp\Message\SendWelcomeEmail: asyncApp\MessageHandler\SendWelcomeEmailHandler: asyncApp\Message\: asyncphp bin/console messenger:transport:setup-transportsphp bin/console messenger:consume async --limit=10--limitphp bin/console debug:messenger