8000 [Messenger] Configure a handler to subscribe to messages by their interface/parent class · Issue #27076 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[Messenger] Configure a handler to subscribe to messages by their interface/parent class #27076

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
kbond opened this issue Apr 27, 2018 · 13 comments

Comments

@kbond
Copy link
Member
kbond commented Apr 27, 2018
Q A
Bug report? no
Feature request? yes
BC Break report? no
RFC? yes
Symfony version 4.1

With MessageSubscriberInterface::getHandledMessages() we can return an array of classes that should be handled but this requires knowing the exact classes before hand. What if we wanted all messages that implement an interface to be handled by a handler?

One solution I came up with was to loop through get_declared_classes() in MessageSubscriberInterface::getHandledMessages() and return the classes that implement an interface but this seems clunky (and perhaps error prone).

Any thoughts on how we can handle this?

@yceruto
Copy link
Member
yceruto commented Apr 27, 2018

Maybe related to #27034 ?

@ro0NL
Copy link
Contributor
ro0NL commented Apr 27, 2018

In theory you could decorate the bus and dispatch e.g. an EventMessage that wraps the original message (if it implements X). Then you can listen for any EventMessage being dispatched..

@kbond
Copy link
Member Author
kbond commented Apr 27, 2018

Yes, this is how I handle this situation with simple-bus. Alternatively, a middleware could be used.

However, I feel like placing the logic in the handler would make understanding/debugging/refactoring easier.

@sroze
Copy link
Contributor
sroze commented Apr 27, 2018

One solution I came up with was to loop through get_declared_classes() in MessageSubscriberInterface::getHandledMessages() and return the classes that implement an interface but this seems clunky (and perhaps error prone).

I think that this is the right one. But I'd do this when registering the handlers within the FrameworkBundle when the message is an interface or abstract class :)

@kbond
Copy link
Member Author
kbond commented Apr 27, 2018

Right, that's when MessageSubscriberInterface::getHandledMessages() is called, correct? In the MessengerPass.

I could easily make a helper trait:

class MySubscriber implements MessageSubscriberInterface
{
    use MyMessageSubscriberHelper;

    public function __invoke(MyInterface $event)
    {
        // ...
    }

    protected function getHandledInterface(): string // abstract method in MyMessageSubscriberHelper
    {
        return MyInterface::class;
    }
}

@kbond
Copy link
Member Author
kbond commented Apr 27, 2018

Or, if MessageSubscriberInterface::getHandledMessages() is changed to iterable, something like:

public static function getHandledMessages(): iterable
{
    return new MessageImplements(MyInterface::class);
}

@sroze
Copy link
Contributor
sroze commented Apr 28, 2018

We are going to change the MessageSubscriberInterface::getHandledMessages() signature from a "EventSubscriber-like" to something more explicit and easily configurable:

static function configureHandledMessages(Configurator $config)
{
    $config->handleMessageClass(MyMessage::class):
    $config->handleMessageInterface(MyInterface::class):
}

This has been discussed in here #27034 (comment) and in the core team, as we know the subscriber syntax is confusing for a lot of people and not explicit at all. The $config->handleXXX will be easy to discover for newcomers (typically, the auto-completion will work, first).

@kbond
Copy link
Member Author
kbond commented May 7, 2018

Now that MessageSubscriberInterface::getHandledMessages() is (will be) iterable would it make sense to have a helper class like described in #27076 (comment) or should this not be provided by the framework?

@nicolas-grekas
Copy link
Member

static function configureHandledMessages(Configurator $config)

for the record, this proposal has been rejected, see #27034 (comment)

@kbond could be worth giving it a try. The iterable should yield only basic arrays of course.

@sroze
Copy link
Contributor
sroze commented May 8, 2018

Can we try to find a smaller scope for this discussion? "Determine handled messages dynamically" is too broad. Is it about "Configure a handler to subscribe to messages by their interface/parent class"? 🤔

@kbond kbond changed the title [Messenger] Determine handled messages dynamically [Messenger] Configure a handler to subscribe to messages by their interface/parent class May 8, 2018
@kbond
Copy link
Member Author
kbond commented May 8, 2018

Sure, I changed the title.

What about an alternative HandlerLocator that has similar logic for handlers as #27184 proposes for finding senders?

@sroze sroze closed this as completed Aug 28, 2018
fabpot added a commit that referenced this issue Aug 29, 2018
… (sroze)

This PR was merged into the 4.2-dev branch.

Discussion
----------

[Messenger] Allow interfaces to be type-hinted as well

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #27076
| License       | MIT
| Doc PR        | ø

Interfaces can be type-hinted as well for the message handlers.

Commits
-------

2dbbfbd Allow interfaces to be type-hinted as well
@kojidev
Copy link
kojidev commented Dec 11, 2018

Well great, but how do I avoid sending the message to multiple handlers now if one message extends from another?
handles in messenger.message_handler does not work

@chalasr
Copy link
Member
chalasr commented Dec 11, 2018

@kojidev Please consider opening a new issue with enough details to reproduce, comments on closed tickets are likely to be lost.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants
0