Plugin Development: Model Events

Previous Section: Form Requests


SupportPal was built with Eloquent ORM, an ActiveRecord implementation with the idea that each record, be it a ticket, user or even an activity log message is a model. Each model has a lifecycle, firing different events when the model is created, updated or deleted. Model events allow you to hook on to these events and use or update the model data as needed.

Contents

Why Use Model Events?

Model events let you listen for changes to a given model and lets you perform an action or alter the model data before the event completes. Example cases where this is useful:

Available Model Events

Model events are split in to two, with a before and after event for each possible model change.

Before Event After Event Description
creating created Fired when a new model has been created and saved for the first time.
updating updated Fired when an existing model has been updated.
saving saved Fired when either a new model has been created or an existing model has been updated.
deleting deleted Fired when a model has been deleted.

The before events are most useful when checking what has changed and allows modify the data before it completes. Returning false in the listener for a before event would stop the operation from completing altogether. The after events are useful when you need to perform an action after the model has changed.

Model event listeners must be declared in the main controller constructor, and are written in the following form.


    Model::created(function ($item) {
       ...
    }

See our examples below to see how they can be used in your plugin.

Example: User Profile Saved

We would like to track when a user has been created or their profile has updated and send that data to another application that we're in sync with.

To simplify this, we can just post all updates to the other application even if none of the actual fields we send have actually updated, so we can use the after saved event on the User model. The thing to take care with is ensuring you only post for confirmed users and not operators who are also covered by the User model.


    // Register user saved event
    \App\Modules\User\Models\User::saved(function ($user) {
        // Only if it's a user and they're confirmed
        if (! $user->isOperator() && $user->confirmed) {
            // Get user ID from other application, or start creating new user
            // Build data in an array from model
            // Send data via API
        }
    }

Example: Ticket Status Changed

We would like to track when the status is changed on a ticket.

We must use the before event on the Ticket model as otherwise we won't know if it was the status or something else that caused the event. We use the isDirty model function to track what has changed from the model's original attributes, so we know if status_id is dirty then it means the status has indeed changed. Inside the listener, we create a copy of the model for any additional work we want to do as we don't want to modify it before it's updated.


    // Register ticket updating event
    \App\Modules\Ticket\Models\Ticket::updating(function ($ticket) {
        // Status changed
        if ($ticket->isDirty('status_id')) {
            // Get old name
            $oldStatus = $ticket->status->name;

            // Create a copy of the model, as we don't want to edit the original
            $model = $ticket->replicate();

            // Remove current relation and reload it
            unset($model->status);
            $model->load('status');

            // Get new name
            $newStatus = $model->status->name;
        }
    }

Next Section: Extending Templates