Skip to content

Conversation

@gehrisandro
Copy link

@gehrisandro gehrisandro commented May 27, 2025

This PR introduces an event alias map similar to Laravels MorphMap.

Motivation

When an alias for an event class is defined, the alias is stored in the type attribute of the events instead of the fully qualified class name. This has two main benefits:

  • The event type is more readable. For example, instead of App\Events\Users\UserCreated just user::created
  • Refactoring the event class (renaming; changing namespace) does not require an updated of previously stored events

Usage

The behaviour is similar to Laravels MorphMap.

Define the event map in one or more service providers:

// AppServiceProvider.php
use Thunk\Verbs\Event;
use App\Events\Users\UserCreated;

Event::eventMap([
    'user::created' => UserCreated::class,
]);

If you want to ensure every event has an alias defined:

// AppServiceProvider.php
use Thunk\Verbs\Event;

Event::requireEventMap();

After defining the map, events are used as before:

use App\Events\Users\UserCreated;

UserCreated::fire(...);

Backwards compatibility

Even I would not recommend it, it would be possible to start using the event map even some events have been stored before. Restoring an event from the database works regardless if the type is an alias or a fully qualified class name.
But this would prevent you from refactoring the event class as mentioned above.

@samlev
Copy link

samlev commented May 27, 2025

Could (should? does?) This extend to states as well as events?

*
* @var array<string, class-string<Event>>
*/
public static array $eventMap = [];
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this should be public, and be on the Event abstract class. This is something that you would typically push into the service that handles event resolution, then from there it can be stored as a stateful, non-static property so that it can't get easily overwritten or altered outside of a service provider.

I would feel a lot more comfortable if this was managed via the Verbs service, and exposed via the Verbs facade, e.g.:

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Verbs::eventMap([
            'some-event' => \App\Events\SomeEvent::class,
        ]);
        Verbs::requireEventMap();
        Verbs::stateMap([
            'some-state' => \App\States\SomeState::class,
        ]);
        Verbs::requireStateMap();
    }
}

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💯, see my comment below.

My initial intention was to make it more similar to Laravel where the morph map is on the Relation class.

@gehrisandro
Copy link
Author

Could (should? does?) This extend to states as well as events?

Probably it should, but currently it does not 😅

We could add the same on State. Something like State::stateMap([...]).

Another option would be to move all methods to the Verbs facade:

// AppServiceProvider.php

use Thunk\Verbs\Facades\Verbs;

Verbs::eventMap([...]);
Verbs::stateMap([...]);
Verbs::requireMaps();

@gehrisandro
Copy link
Author

Are there any opinions from @inxilpro @DanielCoulbourne on this?

If you see a chance to get this feature into Verbs I would love to continue on this PR.

@inxilpro inxilpro added blocks 1.0 We can't release v1.0 until this is merged labels Jun 17, 2025
@inxilpro
Copy link
Contributor

Definitely think this should happen! Will look into it soon.

@gehrisandro
Copy link
Author

Definitely think this should happen! Will look into it soon.

Great 🎉

If there is something I can help with, just let me know.

@gehrisandro
Copy link
Author

Definitely think this should happen! Will look into it soon.

Hi @inxilpro

Did you by any chance already look into it?

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

Labels

blocks 1.0 We can't release v1.0 until this is merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants