如何避免在 Symfony Messenger 中处理来自“子”类的消息?

Posted

技术标签:

【中文标题】如何避免在 Symfony Messenger 中处理来自“子”类的消息?【英文标题】:How to avoid handling messages from "child" classes in Symfony Messenger? 【发布时间】:2020-09-19 11:52:36 【问题描述】:

我想我在文档中遗漏了一些东西,但问题很简单。

假设我有一条 MessageOneMessageTwo 类的消息,它扩展了 MessageOne

我还有MessageOneHandler 应该处理MessageOne

__invoke(MessageOne $messageOne)

MessageTwoHandler 应该只处理MessageTwo

__invoke(MessageTwo $messageTwo)

问题是当MessageTwo 被调度时,它同时被MessageHandlerOneMessageHandlerTwo 处理。是的,由于继承,这是完全明智的,一切在逻辑上都是正确的,但是有什么“symfony”方法可以防止这种情况发生吗?

当然,我可以通过重做这些类的继承来解决这个问题,但是有没有更好的方法呢?

此外,debug:messenger 按预期显示所有内容,每个消息类一个处理程序,没有继承问题。

【问题讨论】:

【参考方案1】:

继承很少会成为适合消息的神。

如果MessageTwo extends MessageOne,那么$messageTwo instanceof MessageOne 将返回true,就这么简单。

此外,消息应该非常简单和轻量级,因此代码重复通常不应该成为问题。但如果出于某种原因您确实需要在消息类之间重用某些代码,您有几个选择:

您可以将处理短路,以便如果get_class($message) !== MessageOne::class 然后处理程序可以在不做任何工作的情况下返回......但我个人认为这将是一个脆弱的设计。

更好的选择是简单地为您的消息重新设计继承模型。

MessageOneMessageTwo 之间的共享逻辑可以移动到父级 AbstractMessage,两者都继承自该父级。处理程序会正确地键入提示具体的消息类型,不会造成混淆。

根据您要重用的代码类型,您可以将共享代码移动到Trait 或具有静态方法的帮助器类。如果其中任何一个好,将完全取决于您的应用程序的具体情况,最终将是一个意见问题。

【讨论】:

是的,我已经选择了选项 1。所以看起来我没有遗漏任何东西,一切都如预期的那样?

以上是关于如何避免在 Symfony Messenger 中处理来自“子”类的消息?的主要内容,如果未能解决你的问题,请参考以下文章

在 Symfony Messenger 组件中使用独立的发件人

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

如何使用 Behat 测试在多总线场景中调度 Symfony Messenger 事件?

Symfony Messenger 如何确定应由哪个处理程序处理每种类型的消息?

Symfony messenger 和 mailer:如何添加 binding_key?

如何关闭 symfony messenger 组件的日志记录