Skip to main content
Version: v8.x

Events & Listeners

phpVMS dispatches a number of events you can subscribe to from your module — when a PIREP is filed, a flight is bid on, a user registers, and so on. The full list of available events lives in the core app/Events directory.

Subscribing follows the standard Laravel events pattern.

Listening to phpVMS events

1. Generate a listener

php artisan module:make-listener PirepAcceptedListener Sample --event=PirepAccepted
# → Modules/Sample/app/Listeners/PirepAcceptedListener.php

Pass --queued if you want the listener to run on a queue rather than synchronously:

php artisan module:make-listener PirepAcceptedListener Sample \
--event=PirepAccepted --queued

2. Implement handle()

namespace Modules\Sample\Listeners;

use App\Events\PirepAccepted;
use Illuminate\Support\Facades\Log;

class PirepAcceptedListener
{
public function handle(PirepAccepted $event): void
{
Log::info('Received PIREP', [$event->pirep]);
}
}

The argument passed to handle() is the event class itself — open the event under app/Events to see what data is exposed (e.g. $event->pirep, $event->user).

3. Register the listener

Register it in the module's EventServiceProvider. If you don't have one yet, generate it:

php artisan module:make-event-provider EventServiceProvider Sample

Then add your listeners to the $listen array:

namespace Modules\Sample\Providers;

use App\Events\PirepAccepted;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Modules\Sample\Listeners\PirepAcceptedListener;

class EventServiceProvider extends ServiceProvider
{
protected $listen = [
PirepAccepted::class => [
PirepAcceptedListener::class,
],
];
}

Finally, register the new provider from your module's main service provider:

// Modules/Sample/app/Providers/SampleServiceProvider.php

public function register(): void
{
$this->app->register(RouteServiceProvider::class);
$this->app->register(EventServiceProvider::class);
}

Dispatching your own events

Modules can dispatch their own events too — useful when other addons (or the operator's customisations) might want to react to something that happens inside your module.

php artisan module:make-event PostWasPublished Sample
# → Modules/Sample/app/Events/PostWasPublished.php

php artisan module:make-listener NotifyAdminListener Sample --event=PostWasPublished

Then dispatch from anywhere — controllers, services, observers:

use Modules\Sample\Events\PostWasPublished;

PostWasPublished::dispatch($post);
// or
event(new PostWasPublished($post));

Listening to module lifecycle events

The module system itself dispatches events when modules are enabled, disabled, created, or destroyed. You can hook into them to run setup, teardown, or notification logic.

use Nwidart\Modules\Events\ModuleEvent;

protected $listen = [
ModuleEvent::ENABLED => [
\Modules\Sample\Listeners\OnModuleEnabled::class,
],
ModuleEvent::DISABLING => [
\Modules\Sample\Listeners\OnModuleDisabling::class,
],
];
ConstantWhen it fires
BOOTEach module finishes booting on every request.
REGISTEREach module is registered.
ENABLINGJust before a module is enabled.
ENABLEDAfter a module is enabled.
DISABLINGJust before a module is disabled.
DISABLEDAfter a module is disabled.
CREATINGBefore a module is created via module:make.
CREATEDAfter module:make completes.
DELETINGBefore module:delete.
DELETEDAfter module:delete.
USEDA module is selected with module:use.
UNUSEDmodule:unuse.

Dependency injection

Listeners are resolved out of the Laravel container, so any constructor dependencies (services, core models, clients) are auto-injected:

namespace Modules\Sample\Listeners;

use App\Events\PirepAccepted;
use App\Services\PirepService;

class PirepAcceptedListener
{
public function __construct(
private PirepService $pirepSvc,
) {}

public function handle(PirepAccepted $event): void
{
// $this->pirepSvc is ready to use
}
}

See Patterns & Conventions → Dependency injection for the recommended constructor-injection style.