Ejecutar acciones cuando un modelo se crea, se edita o se elimina en Laravel
Muchas veces, en nuestros back-end, tenemos que realizar varias acciones una vez un registro se inserta / edita. Por ejemplo:
- Enviar un e-mail cuando se crea un pedido o cambia de estado
- Comprimir una imagen o un vídeo al subirla a la web
- Ejecutar un job de importación de datos, etc.
Por ejemplo, para realizar un pedido nuestro código podría ser así:
<?php
namespace App\Http\Controllers;
use App\Models\Order;
use App\Mail\NewOrderEmail;
use Illuminate\Http\Request;
use Mail;
class OrderController extends Controller
{
public function executeOrder(Request $request)
{
// validation...
// $request->validate([...]);
$order = new Order();
// ...
$order->save();
Mail::to($order->user->email)->send(new NewOrderEmail($order));
Mail::to(config('platform.admin.email'))->send(new NewOrderEmail($order));
}
}
Aunque este código no esté mal, aún se puede abstraer esta lógica de "¿qué tiene que pasar cuando se cree un pedido en nuestra plataforma?" a un lugar más "reutilizable". Esta lógica de negocio debería ser la misma y ejecutarse de manera automática independientemente de si el pedido se crea desde la web, a través de la app, a través de la API o a través de un panel de administración interno. Además, ¡idealmente sin repetir el código!
Para ello, Eloquent nos provee con varios eventos a los que podemos escuchar:
Evento | Descripción |
---|---|
retrieved | Un modelo se descarga de la base de datos |
creating | Cuando un modelo se está guardando por primera vez, pero antes de guardarse |
created | Cuando un modelo se guarda por primera vez |
updating | Justo antes de ejecutar el UPDATE del modelo en base de datos |
updated | Cuando un modelo se actualiza |
saving | Cuando un modelo se está guardando (sea para crear o editar) |
saved | Cuando un modelo se ha guardado |
deleting | Justo antes de eliminar un modelo |
deleted | Cuando un modelo es eliminado |
trashed | Cuando un modelo es marcado como deleted_at en la base de datos |
forceDeleted | Cuando un modelo se elimina permanentemente de la base de datos |
restoring | Cuando se está restaurando un modelo de la base de datos |
restored | Cuando se restaura un modelo de la base de datos |
replicating | Cuando se duplica un modelo |
Desde Eloquent podemos escuchar a estos eventos y ejecutar acciones:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Order extends Model
{
/**
* The "booted" method of the model.
*
* @return void
*/
protected static function booted()
{
static::created(function (Order $order) {
Mail::to($order->user->email)->send(new NewOrderEmail($order));
Mail::to(config('platform.admin.email'))->send(new NewOrderEmail($order));
});
}
}
Además, puedes definir directamente que la función se ejecute en el sistema de colas:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Order extends Model
{
/**
* The "booted" method of the model.
*
* @return void
*/
protected static function booted()
{
static::created(queueable(function (Order $order) {
Mail::to($order->user->email)->send(new NewOrderEmail($order));
Mail::to(config('platform.admin.email'))->send(new NewOrderEmail($order));
}));
}
}
De esta forma, da igual desde donde se haya creado el pedido, siempre se enviará un email al usuario y al administrador de la plataforma sin tener que reutilizar código.