Weave Code
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

hyperf/event

hyperf/event is a lightweight event dispatcher for Hyperf applications. Define events and listeners, dispatch synchronously or via async mechanisms, and keep your domain decoupled. Integrates cleanly with Hyperf’s DI and coroutine-friendly runtime.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require hyperf/event
    

    Ensure the package is auto-loaded in composer.json or manually register in config/autoload.php:

    'dependencies' => [
        Hyperf\Event\EventDispatcher::class,
    ],
    
  2. Define an Event: Create a class implementing Hyperf\Event\Contract\EventInterface (or extend Hyperf\Event\Event):

    namespace App\Events;
    
    use Hyperf\Event\Event;
    
    class OrderCreated extends Event
    {
        public function __construct(public int $orderId, public array $data) {}
    }
    
  3. Dispatch an Event: Inject EventDispatcher and dispatch:

    use Hyperf\Event\EventDispatcher;
    
    class OrderController
    {
        public function __construct(private EventDispatcher $dispatcher) {}
    
        public function createOrder()
        {
            $this->dispatcher->dispatch(new OrderCreated(123, ['items' => []]));
        }
    }
    
  4. Register a Listener: Define a listener class implementing Hyperf\Event\Contract\ListenerInterface:

    namespace App\Listeners;
    
    use App\Events\OrderCreated;
    use Hyperf\Event\Contract\ListenerInterface;
    
    class SendOrderConfirmation implements ListenerInterface
    {
        public function handle(OrderCreated $event)
        {
            // Logic to send confirmation
        }
    }
    
  5. Configure Listeners: Bind listeners in config/autoload/event.php:

    return [
        'listen' => [
            OrderCreated::class => [
                \App\Listeners\SendOrderConfirmation::class,
            ],
        ],
    ];
    

First Use Case: Async Processing

Dispatch an event to trigger background tasks (e.g., sending emails, updating analytics) without blocking the request:

// Dispatch
$this->dispatcher->dispatch(new UserRegistered($userId));

// Listener (runs in background via Swoole coroutines)
class HandleUserRegistration implements ListenerInterface
{
    public function handle(UserRegistered $event)
    {
        go(function () use ($event) {
            // Non-blocking email sending
            sendWelcomeEmail($event->userId);
        });
    }
}

Implementation Patterns

1. Event-Driven Workflows

  • Decouple Components: Use events to communicate between services (e.g., PaymentProcessedInventoryUpdate).

    // Dispatch payment event
    $this->dispatcher->dispatch(new PaymentProcessed($orderId, $amount));
    
    // Listener for inventory
    class UpdateInventory implements ListenerInterface
    {
        public function handle(PaymentProcessed $event)
        {
            reduceInventory($event->orderId, $event->amount);
        }
    }
    
  • Fan-Out Pattern: Broadcast events to multiple listeners:

    // config/autoload/event.php
    return [
        'listen' => [
            PaymentProcessed::class => [
                UpdateInventory::class,
                SendReceipt::class,
                LogPayment::class,
            ],
        ],
    ];
    

2. Middleware for Events

Attach middleware to events for cross-cutting concerns (e.g., logging, auth):

// Define middleware
class LogEventMiddleware
{
    public function __invoke($event, $next)
    {
        \Log::info("Event dispatched: " . get_class($event));
        return $next($event);
    }
}

// Apply middleware to an event
$this->dispatcher->dispatchWithMiddleware(
    new OrderCreated(123, []),
    [LogEventMiddleware::class]
);

3. Dynamic Event Routing

Route events dynamically based on conditions (e.g., tenant ID):

// In a service or controller
$event = new OrderCreated(123, ['tenant_id' => 'acme']);
$this->dispatcher->route($event, 'tenant_' . $event->data['tenant_id']);

4. WebSocket Integration

Broadcast events to WebSocket clients:

// Define a WebSocket event
class OrderUpdated extends Event
{
    public function broadcastOn(): string
    {
        return 'private-order.' . $this->orderId;
    }
}

// Listener to push to WebSocket
class BroadcastOrderUpdate implements ListenerInterface
{
    public function handle(OrderUpdated $event)
    {
        $this->dispatcher->dispatch(new WebSocketEvent(
            $event->broadcastOn(),
            $event
        ));
    }
}

5. Priority Events

Use priority queues for time-sensitive events:

// Dispatch with priority
$this->dispatcher->dispatchWithPriority(
    new HighPriorityEvent(),
    'high'
);

// Configure priority listeners
return [
    'listen' => [
        HighPriorityEvent::class => [
            ['\App\Listeners\ProcessUrgentTask', 'high'],
        ],
    ],
];

6. Laravel Event Adapter

Bridge Laravel events to Hyperf (if migrating or using both):

// Configure in config/autoload/event.php
return [
    'adapters' => [
        'laravel' => [
            'enabled' => true,
            'fallback_to_redis' => env('FALLBACK_TO_REDIS', false),
        ],
    ],
];

// Dispatch a Laravel event (auto-converted)
event(new \App\Events\LaravelEvent());

7. Coroutines for Async Processing

Leverage Swoole coroutines for non-blocking listeners:

class AsyncTaskListener implements ListenerInterface
{
    public function handle(Event $event)
    {
        go(function () use ($event) {
            // Non-blocking I/O (e.g., HTTP requests, DB writes)
            $result = \Http::post('https://api.example.com', $event->data);
            \Log::info("Async task completed: " . $result);
        });
    }
}

8. Event Filtering

Filter events before dispatching (e.g., validate payloads):

// Middleware to filter events
class ValidateEventPayload
{
    public function __invoke($event, $next)
    {
        if (!isset($event->data['required_field'])) {
            throw new \InvalidArgumentException("Missing required field");
        }
        return $next($event);
    }
}

// Apply to all events
$this->dispatcher->pipe(ValidateEventPayload::class);

Gotchas and Tips

Pitfalls

  1. Blocking Listeners:

    • Avoid synchronous I/O (e.g., file_get_contents, DB::table()->get()) in listeners. Use coroutines (go) or async methods.
    • Fix: Wrap blocking code in go:
      go(function () {
          $data = \Http::get('https://api.example.com');
      });
      
  2. Event Ordering:

    • Hyperf does not guarantee event ordering by default. Use EventTransaction for critical paths:
      use Hyperf\Event\EventTransaction;
      
      $transaction = new EventTransaction();
      $transaction->dispatch(new EventA());
      $transaction->dispatch(new EventB());
      $transaction->commit();
      
  3. Memory Leaks:

    • Unbound listeners or event objects retained in memory can cause leaks. Ensure proper cleanup in long-running processes.
    • Fix: Use weak references or limit event retention.
  4. WebSocket Payload Size:

    • Binary payloads (e.g., protobuf) may hit size limits. Monitor EventWebSocket logs for truncation warnings.
    • Fix: Compress large payloads or split into chunks.
  5. Laravel Adapter Quirks:

    • The Laravel event adapter may not support all Laravel-specific features (e.g., ShouldBroadcastNow). Test thoroughly.
    • Fix: Use EventWebSocket for broadcasting instead of Laravel’s ShouldBroadcast.
  6. Priority Misconfiguration:

    • Incorrect priority settings can lead to events being processed out of order or dropped.
    • Fix: Validate priority queues in config/autoload/event.php:
      'priorities' => ['low', 'normal', 'high', 'critical'],
      
  7. Coroutine Deadlocks:

    • Nested coroutines or improper yield usage can cause deadlocks.
    • Fix: Avoid recursive coroutines and use timeouts:
      $result = yield \Swoole\Coroutine::create(function () {
          return \Http::get('https://api.example.com', ['timeout' => 2]);
      });
      

Debugging Tips

  1. Enable Event Logging:

    // config/autoload/event.php
    'debug' => true,
    

    Logs dispatched events and listeners to storage/logs/hyperf.log.

  2. Trace Events: Use the hyperf:event:trace CLI tool to trace event flows:

    php bin/hyperf.php event:trace OrderCreated
    
  3. Monitor WebSocket Connections: Check active WebSocket connections:

    php bin/hyperf.php webs
    
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.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor