Laravel decouples an event dispatch from its listener(s), linked by the event
class: event(new OrderShipped($order)) has no static edge to the
handle(OrderShipped $event) that runs it (usually a separate app/Listeners/
class). laravelEventEdges bridges each event(new X(...)) site -> every
listener's handle for X.
Two registration mechanisms, both real and both needed (built together):
- (A) auto-discovery: a typed handle(EventType $e) first param, read from the
method declaration source (PHP method nodes carry no signature, like C#); a
handle(A|B $e) union is split into two events.
- (B) the `protected $listen = [XEvent::class => [Listener::class, ...]]` map in
an EventServiceProvider, parsed from comment-stripped source (so a
fully-commented map on an auto-discovery app contributes nothing). This is the
only way to link a listener whose handle() is untyped.
Job exclusion is free: queued jobs dispatch via ::dispatch()/dispatch() (not
matched) and their handle() takes an injected service, never an event type, so
matching only event(new X) excludes them by construction. `use Dispatchable` is
not keyed on (unreliable in real apps).
Surfaces as `dynamic: laravel event` via the generic synth-edge fallback.
Validated 100% precision on two grep-confirmed repos exercising both
mechanisms: koel (small, populated $listen map, 9 edges incl. the untyped-handle
case and a fan-out) and firefly-iii (large, pure auto-discovery / empty $listen,
141 edges, 0 source/target false positives, 0 namespace mismatch, union split
verified); 0 on the guzzle control. Namespace-agnostic (FireflyIII\ not
hardcoded). Node-stable (pure edge synth). Suite 1623 green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>