Skip to content

Auto discovering Event-Listeners across modules #2128

@EhabAmawi

Description

@EhabAmawi

Versions:

  • laravel-modules Version: 12.0.4
  • Laravel Version: 12.34.0
  • PHP Version: 8.4

Description:

Laravel 12 introduced a new withEvents() method in bootstrap/app.php to configure event discovery directories. According to the Laravel 12 documentation, you can
specify custom listener directories using wildcards:

->withEvents(discover: [
    __DIR__.'/../app/Listeners',
    __DIR__.'/../Modules/*/app/Listeners',  // Should discover all module listeners
])

However, this does not work for discovering listeners in module directories when using nwidart/laravel-modules. Listeners in module directories (e.g., Modules/Loyverse/app/Listeners/SyncLoyversePoints.php) are not auto-discovered for events in the main application (e.g., App\Events\LoyaltyPointsAwarded), even though:

  1. The listener has a proper handle(EventClass $event) method signature
  2. The module's EventServiceProvider has $shouldDiscoverEvents = true
  3. The path is correctly specified in withEvents()

The only workaround is to manually register the event-listener mapping in the module's EventServiceProvider:

  protected $listen = [
      \App\Events\LoyaltyPointsAwarded::class => [
          \Modules\Loyverse\Listeners\SyncLoyversePoints::class,
      ],
  ];

This defeats the purpose of Laravel 12's improved auto-discovery feature.

Steps To Reproduce:

  1. Install a fresh Laravel 12 application
  2. Install nwidart/laravel-modules: composer require nwidart/laravel-modules
  3. Create a module: php artisan module:make Loyverse
  4. Create an event in the main app: php artisan make:event LoyaltyPointsAwarded
  5. Create a listener in the module at Modules/Loyverse/app/Listeners/SyncPoints.php
  <?php
  namespace Modules\Loyverse\Listeners;

  use App\Events\LoyaltyPointsAwarded;

  class SyncPoints
  {
      public function handle(LoyaltyPointsAwarded $event): void
      {
          \Log::info('Listener triggered');
      }
  }
  1. Configure event discovery in bootstrap/app.php:
  ->withEvents(discover: [
      __DIR__.'/../app/Listeners',
      __DIR__.'/../Modules/*/app/Listeners',
  ])
  1. Ensure the module's EventServiceProvider is registered and has $shouldDiscoverEvents = true
  2. Clear caches: php artisan optimize:clear
  3. Check registered listeners: php artisan event:list

Expected Result: The SyncPoints listener should appear under LoyaltyPointsAwarded event.

Actual Result: The listener is not discovered.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions