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

Event Laravel Package

hoa/event

Hoa\Event is a lightweight PHP event library for decoupled, event-driven code. Attach listeners to named events, fire them with data buckets, and use listenable sources to route notifications cleanly across your application. Part of the Hoa project.

View on GitHub
Deep Wiki
Context7

Getting Started

hoa/event is not a Laravel package — no service provider, no facade, no config file, no Blade/directive integration. It is a standalone PHP 5-era event/messaging micro-library that you composer require hoa/event:^1.0 and instantiate by hand. There is nothing to publish and nothing to register in config/app.php.

Where to look first (in this order):

  1. README.md — the only docs that exist; the Hoa project docs site is the "real" manual.
  2. Hoa/Event/Event.php — the event object; getEventId(), getSource(), getBucket().
  3. Hoa/Event/Bucket.php — the object actually handed to every listener. This is the API you will touch in 90% of your listener closures: getData() / setData() / getSource().
  4. Hoa/Event/Listenable.php + Hoa/Event/Listener.php — the on() / getListener() / fire() contract that sources implement.

Minimal first use case — a local, in-process hook inside one of your own classes, wrapped so it doesn't leak into the rest of the app:

// composer require hoa/event:^1.0
use Hoa\Event\{Bucket, Event, Listenable, Listener};

final class OrderHookPoint implements Listenable
{
    private Listener $listener;

    public function __construct()
    {
        $this->listener = new Listener(); // check ctor signature in Listener.php
    }

    public function on($eventId, $listener)        { return $this->listener->on($eventId, $listener); }
    public function getListener($eventId = null)   { return $this->listener->getListener($eventId); }
    public function fire(Event $event, array $o = []) { return $this->listener->fire($event, $o); }
}
$hooks = new OrderHookPoint();
$hooks->on('order:placed', function (Bucket $bucket) {
    $data = $bucket->getData();
    $bucket->setData($data + ['audited' => true]); // visible to the next listener
});

Honest framing for a Laravel team: this buys you nothing that Illuminate\Contracts\Events\Dispatcher doesn't already give you — and Laravel's dispatcher gives you priorities, subscribers, wildcards, queued/broadcast events, and Event::fake() in tests. 0 dependents, archived since 2017‑08‑30. Reach for it only if you are porting legacy Hoa code (hoa/stream, hoa/websocket) and need API parity, not for new work.

Implementation Patterns

Bucket-as-payload (the one genuinely distinct idea). Listeners don't get a cloned value object; they all receive the same Bucket and mutate its data. Later listeners see earlier mutations. This is a fold/pipe, not a notification fan-out — model it explicitly, e.g. a "normalise → validate → enrich → persist" chain, and document that order matters.

Adapter to the Laravel dispatcher. If you must keep Hoa semantics while living in a Laravel app, keep the boundary thin: inside the Hoa listener, translate to a Laravel event and event(new ...). Do not let Hoa event IDs escape the adapter class — one file, one direction.

Fire-and-forget inside a service. Use it as a plugin seam for classes you own (a parser, an exporter) where you want third parties to hook into a fire() call without depending on the container. Constructor-inject the Listenable wrapper so you can swap it for a fake in tests.

Bridge to existing Laravel events. Wrap Illuminate\Events\Dispatcher behind the Hoa interface rather than the reverse: implement Listenable::on() as $dispatcher->listen($eventId, $listener). This keeps new code on Laravel's scheduler and lets you delete the Hoa shim later without touching call sites.

Naming convention. Hoa source IDs use hoa://event/...-style strings; follow a dotted convention of your own (order:placed, order:saved) and centralise the constants. There is no string-matching or wildcard engine here, so typos fail silently — everything is keyed by exact array index.

Gotchas and Tips

  • Abandoned + pre-PHP 8. Last release 2017. Expect deprecation noise on PHP 8.1+ and no fixes for dynamic properties, Xcallable coercion quirks, or hoa/consistency transitive constraints that can pin your other Hoa packages. Run the full suite on your target PHP before committing.
  • Silent no-ops. fire() on an event ID with no listeners simply does nothing and returns no error. Add a debug helper that dumps getListener() contents when an expected hook doesn't run — this is the debugging trap.
  • Exceptions kill the chain. A throwing listener aborts subsequent listeners mid-mutation, leaving the bucket half-transformed. Wrap listener bodies in try/catch and report through Laravel's handler if the pipeline must survive.
  • Listenable has no priorities. Registration order is execution order. If order matters, either sort at the call site or keep listeners idempotent; there's no $priority argument to lean on.
  • No queueing, batching, broadcasting, or retries. Anything async is your problem — dispatch a Laravel job from inside the listener.
  • Listener retention = memory leaks. Long-lived workers (Octane, queue workers) holding a Listener accumulate closures forever; there is no forget()/removeListener() in the public contract. Rebuild the wrapper per request/job, or cap registrations.
  • Laravel testing gap. Event::fake() will not intercept these. You must hand-roll a spy listener (a closure that appends to an array) or inject a stub Listenable. Budget for that in any test plan.
  • Extension point is the interface, not config. Everything is code: implement Hoa\Event\Listenable (or compose Hoa\Event\Listener) and delegate. There's no container binding, no config/event.php, no facade accessor — which also means no accidental coupling if you keep the wrapper final and narrow.
  • Migration tip. Because on($id, callable) and fire(Event) are trivially mappable to Dispatcher::listen() / Dispatcher::dispatch(), write the wrapper first and treat hoa/event as an implementation detail from day one. That is the only way this dependency stays removable.
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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console