hirethunk/verbs
Verbs is a PHP event sourcing package for Laravel artisans. It delivers the benefits of event sourcing while minimizing boilerplate and jargon, making it simpler to model behavior and build systems by thinking in actions (verbs) instead of nouns.
#[StateId], handle() methods) to minimize friction.team_id, user_preferences) enables cross-cutting concerns without polluting event classes, a common pain point in event sourcing.verbs:event and verbs:state Artisan commands scaffold boilerplate, reducing initial setup time. Attributes like #[AppliesToState] and #[StateId] automate state-event binding.handle() method bridges events to model persistence.Listen attribute (though undocumented in the latest docs) suggests potential for reactive programming with existing Laravel events.apply() vs. handle(), state validation). Teams unfamiliar with CQRS may struggle with:
#[Once] attribute and unlessReplaying guard against idempotency issues, but replay logic must be explicitly designed.validate() failures) can break invariants. Verbs lacks built-in rollback mechanisms for failed events.state_id + event_type composite keys).#[StateId]) may have edge cases in older PHP versions (though Laravel 10+ mitigates this).#[AppliesToChildState])?State (a lightweight alternative to Eloquent) or use Eloquent models directly. Verbs provides a VerbsHistory trait for event history on models.team_id) fits naturally into Laravel’s middleware pipeline.handle() methods running in workers.state_id.Verbs::fake() for mocking events in unit tests).handle() updates Eloquent, while state tracks domain invariants).User model with:
UserState (for domain logic, e.g., trial_expired_at).User Eloquent model (for queries, e.g., users.where('email', ...)).UserRegistered event).validate() in UserRegistered to prevent duplicate emails).UserProfile view built from events).php artisan vendor:publish --tag=verbs-migrations.ServiceProvider (e.g., inject tenant_id from middleware).User::create() → UserRegistered::fire()).handle() methods).PaymentProcessed event triggers notifications).ChargeCreated::fire()) to ensure idempotency.user_id to events (e.g., Verbs::createMetadataUsing(fn () => ['user_id' => auth()->id()])).Listen attribute to react to existing Laravel events (e.g., #[Listen(\Illuminate\Auth\Events\Registered::class)]).OrderPlaced, PaymentAuthorized, InventoryReserved.last_order_at).#[AppliesToChildState] for hierarchical data (e.g., OrderState → OrderItemState).Event::fire() in controllers, jobs, or middleware.validate(State) to enforce invariants.apply(State) to update state immutably.handle() for side effects (e.g., sending emails, updating external systems).#[StateId], #[AppliesToState]) reduce repetitive code (e.g., no need for manual state lookup logic).verbs:event, verbs:state) enforce consistency.How can I help you explore Laravel packages today?