Skip to content

Refactor model boot() business logic into event listeners and action classes #126

@smnmsr

Description

@smnmsr

Problem

Several models contain business logic in boot() methods using Eloquent model events (creating, created, deleting). This mixes persistence concerns with domain logic, making it hard to test, override, or skip in tests.

Affected models:

  • Donor — token generation on creating, logging on created, notifications + logging on deleting
  • Donation — notifications + token + logging on created, logging on deleting

Proposed Solution

Extract each callback into a dedicated action class, triggered by an event listener bound in EventServiceProvider (or via #[Listen] attributes):

  1. Dispatch events (or use Eloquent's built-in eloquent.created: Model etc.)
  2. Create listeners that delegate to action classes
  3. Register bindings in EventServiceProvider

This gives us:

  • Testable, single-responsibility actions
  • Easy to queue, skip, or swap
  • No coupling between model and notification/logging logic

Example

// app/Events/DonationRegisteredEvent.php
final readonly class DonationRegisteredEvent
{
    public function __construct(public Donation $donation) {}
}

// app/Listeners/SendDonationNotifications.php
class SendDonationNotifications
{
    public function handle(DonationRegisteredEvent $event): void
    {
        $event->donation->donor->notify(new DonationRegistered(...));
        $event->donation->athlete->notify(new AthleteNewDonation(...));
    }
}

Scope

  • Donor model: creating, created, deleting callbacks
  • Donation model: created, deleting callbacks
  • Potentially other models with similar patterns discovered during refactoring

Out of Scope

  • Changing the notification content or routes
  • Changing the token generation algorithm

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions