hirethunk / verbs

Verbs is an event sourcing package for PHP artisans
https://verbs.thunk.dev
MIT License
412 stars 32 forks source link

Use states on events directly #169

Closed joshhanley closed 3 weeks ago

joshhanley commented 1 month ago

This PR adds support for using States directly as properties on Events instead of having an ID property with the StateId attribute.

So an event might look like this:

class UserRequestAcknowledged extends Event
{
    public function __construct(
        // Instead of this
        // #[StateId(UserRequestState::class)
        // public int $user_request_id;

        // We can just do this
        public UserRequestState $user_request
    ) {}

    public function apply()
    {
        $this->user_request->acknowledged = true;
    }
}

And can be called like this:

$user_request = UserRequestState::load(snowflake()->make());

UserRequestAcknowledged::commit(
    user_request: $user_request
);

It also supports passing the ID in directly and it will still load and serialise correctly:

$user_id = snowflake()->make();

UserRequestAcknowledged::commit(
    user_request: $user_id
);

Finally I have also added a State::new() helper, to load a new state with a fresh snowflake:

// Instead of this
// $user_request = UserRequestState::load(snowflake()->make());

// We can just do this
$user_request = UserRequestState::new();

UserRequestAcknowledged::commit(
    user_request: $user_request
);

I've also added tests for singleton states, accessing nested states, and even using StateCollections in events.

Using the #[StateId] attribute will still work perfectly fine too.

madebycaliper commented 2 weeks ago

Nice work @joshhanley! love this