Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Observer Laravel Package

phine/observer

Phine Observer provides a clean, flexible observer implementation for Laravel Eloquent models. Hook into events like creating, updating, and deleting with reusable observer classes, keeping side effects out of your models and your code organized.

View on GitHub
Deep Wiki
Context7

Getting Started

phine/observer is a single-purpose, MIT-licensed implementation of the GoF observer pattern, archived by its author and sitting at 5 stars with zero dependents. Treat it as source code to read and vendor, not as a dependency to adopt for the long haul.

Minimal steps:

  1. Install or vendor. If the Packagist entry is still resolvable: composer require phine/observer Because the repo is archived, prefer pinning an exact version or copying src/ into your own namespace — you will not get security patches or PHP-version compatibility fixes.
  2. Read the interfaces first. Open src/ and read the observer/subject contracts before writing anything. They are the entire API surface: an observer registration method (attach/detach), a notification method (notify/update), and a payload parameter. There is no container integration, no priority queue, no configuration.
  3. Confirm your PHP version. The library predates modern PHP typing and is archived; run it against your target PHP runtime in a scratch script before wiring it into production code.
  4. First use case: a small, synchronous, in-process notification list — e.g. a "user registered" hook in a legacy service class that needs to fan out to a mailer, an audit logger, and a cache warmer without the service knowing about them.
// Illustrative of the typical shape — verify names against src/
$subject = new SomeObservable();

$subject->attach(new SendWelcomeEmail());
$subject->attach(new WriteAuditLog());

$subject->notify($user); // each observer's update() runs in registration order

If you are in Laravel, pause here: Laravel's "observers" are Eloquent model observers and are a completely different concept. This package is the generic GoF pattern. Do not mix the two vocabularies in one codebase without a comment explaining which is which.

Implementation Patterns

Implement the observer interface per concern. One class per reaction, not one "GodObserver" that switches on event type. This is the only thing that makes the pattern pay off.

final class SendWelcomeEmail implements ObserverInterface
{
    public function __construct(private Mailer $mailer) {}

    public function update($subject, $arguments = null): void
    {
        $this->mailer->sendWelcome($arguments);
    }
}

Constructor injection, not service location. The library knows nothing about DI containers. Build your observer list in a service provider or a small factory, resolve observers from the container there, and attach them to the subject. This keeps the subject free of framework coupling and makes the whole thing testable with plain doubles.

Attach at composition time, notify at runtime. Register observers once during boot (service provider, bootstrap script, module init) and only call the notify method inside business logic. Don't attach inside request handlers — you'll leak observers across a long-running worker (Octane, RoadRunner, queue workers).

Payload discipline. The notify signature carries a single arguments value. Pass an immutable DTO or an associative array with a stable shape, never a whole Eloquent model you might mutate. Observers that both read and write the payload create invisible ordering dependencies.

Wrap it behind your own interface. Define EventDispatcher-ish contract in your domain, implement it with phine/observer today, swap it for Symfony's EventDispatcher or Laravel's dispatcher tomorrow. Given the archived status, this is the single most important pattern: keep the third-party type out of your public signatures.

Test as a plain unit. Attach a spy observer, invoke the subject, assert the spy recorded the call and payload. No framework bootstrapping required — that's the one genuine advantage this library has over heavier event dispatchers.

Gotchas and Tips

  • Archived means frozen. No PHP 8.1+ enum/readonly support, no typed signatures, no security advisories. Audit src/ for mixed-heavy signatures and any dynamic property access before enabling E_ALL or strict deprecation handling — dynamic properties are fatal-adjacent in modern PHP.
  • Zero dependents is a signal. There is no community, no Stack Overflow corpus, no third-party extensions. You are the maintainer now; fork it into app/Support/Observer if you use it.
  • Laravel already ships a better dispatcher. Event::dispatch() + listeners gives you priority ordering, queued listeners, wildcard matching, and Event::fake() in tests. Reach for this package only if you specifically want a dependency-free, framework-agnostic subject/observer pair inside a library you distribute.
  • No priority or ordering control (verify in source). Observers run in insertion order; if observer B depends on what observer A wrote into the payload, you have an implicit contract that will break the moment someone reorders the attach calls. Make dependencies explicit in the payload or split into two notifications.
  • Exceptions abort the fan-out. A throwing observer typically stops the remaining observers. Catch and log inside observers, or wrap the notify call, depending on whether you want fail-fast or best-effort semantics — decide deliberately per subject.
  • Reference leaks in long-running processes. The subject holds strong references to observers (and observers often hold the subject). In Octane/queue workers, detach in a finally or scope the subject per job. This is the most likely production bug you'll hit.
  • Debugging is manual. No logging, no introspection API. var_dump/dd the attached list, or add a temporary spl_object_id-keyed debug map in your wrapper. If you cannot see who is attached, add a getObservers() accessor in your wrapper class rather than patching the vendor code.
  • Extension points are limited to composition. There's no middleware, no filtering, no "once" semantics. Subclass the observable only to add attach/detach guarding (e.g., reject duplicate observers); everything else belongs in your wrapper.
  • Verdict for day-to-day use: for a greenfield Laravel app, use native events and Eloquent observers — do not add this. For a small, dependency-averse package where you control the bootstrap, copy the ~100 lines into your own namespace, add strict types, and move on.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route