En muchos proyectos es fundamental contar con un historial de cambios que nos permita saber quién modificó qué dato, en qué momento y cuál fue la diferencia antes y después. Este historial de cambios suele conocerse como un sistema de trazabilidad o revisiones (revision history). En este artículo aprenderás a desarrollar, desde cero y sin dependencias adicionales, un sistema que registre la creación, actualización y eliminación de registros en tu aplicación Laravel.
1. ¿En qué consiste nuestro sistema de revisiones?
La idea principal es tener un modelo Revision que guarde la información de:
El usuario que realizó el cambio (usamos un
morphs('owner'), para mayor flexibilidad).El modelo que fue modificado (usamos un
morphs('revisionable')).La columna modificada, junto con su valor anterior y su valor nuevo.
Un campo de comentarios para saber si fue creado, actualizado o eliminado.
Lo lograremos con:
Un modelo y migración
Revisionque almacenará los cambios.Un
traitRevisionableque se inyecta en cualquier modelo que deseemos auditar. Este trait intercepta los eventoscreated,updatedydeleted, y registra en la base de datos la información necesaria.Relaciones polimórficas para vincular el modelo
Revisioncon cualquier otro modelo (p. ej.,Ticket,Article, etc.).
2. Creando el modelo y migración Revision
Lo primero será generar el modelo Revision y su migración. Para ello, ejecuta:
Esto creará el archivo de migración y el modelo. A continuación, ajusta el contenido de la migración (database/migrations/..._create_revisions_table.php) de la siguiente manera:
Ya con la migración lista, podemos definir el modelo Revision:
Con esto, tenemos todo lo necesario para almacenar los cambios en la tabla revisions.
3. El trait Revisionable
Ahora crearemos un trait que se incluirá en cualquier modelo que queramos auditar. Este trait hará uso de los eventos de Eloquent (created, updated, deleted) para capturar los cambios y guardarlos en la tabla revisions.
Crea el archivo app/Traits/Revisionable.php con el siguiente contenido:
¿Cómo funciona?
El trait define una relación polimórfica
revisions()con el modeloRevision.Dentro de
bootRevisionable(), enganchamos tres eventos importantes:created: Para cada columna auditable, se registra una fila que indica que el valor antiguo eranully el nuevo es el que se ha creado.updated: Solo registra una nueva fila cuando detecta que una columna marcada comorevisionableha cambiado.deleted: Marca el valor viejo como el que existía y el nuevo comonull, indicando que se ha eliminado.
Es fundamental que cada modelo defina una propiedad protected array $revisionableColumns donde listemos las columnas que queremos auditar.
4. Ejemplo de uso: Modelo Ticket
Imagina que tenemos un modelo Ticket con la siguiente migración:
En la migración (resumen):
Y el modelo Ticket quedaría así:
Cuando se cree, actualice o elimine un ticket, se registrarán las revisiones correspondientes en la tabla revisions.
5. Otro ejemplo: Modelo Article
De manera análoga, podemos hacer lo mismo con un modelo Article:
Migración:
Modelo:
En este caso, se registrarán los cambios en el title y content cada vez que se modifique o elimine un artículo.
6. Cómo consultar las revisiones
Para acceder al historial de cambios de un modelo, basta con utilizar la relación revisions():
Lo mismo aplica para un Article u otro modelo que use el trait Revisionable.
7. Conclusiones y recomendaciones
Flexibilidad: El uso de relaciones polimórficas permite auditar múltiples modelos con una sola tabla de revisiones.
Escalabilidad: El trait está basado en eventos de Eloquent, por lo que no hay dependencias de paquetes externos.
Control de columnas: Al definir
$revisionableColumns, controlamos exactamente qué campos se registran en las revisiones, evitando sobrecargar la tabla con datos innecesarios.Consideraciones de rendimiento: Cada inserción o actualización genera nuevos registros en la tabla
revisions. Para aplicaciones con mucha actividad, es recomendable monitorizar el tamaño de esta tabla y definir estrategias de limpieza.Seguridad y permisos: El trait actual asume que hay un usuario autenticado con
auth()->user(). En entornos donde esta suposición no sea válida, conviene ajustar la lógica (por ejemplo, para manejar procesos automatizados).
Con esto, ya tienes un sistema de trazabilidad completo que te permitirá ver qué se modificó, quién lo modificó y cuáles eran los valores antes y después de cada cambio. ¡Espero que esta guía te ayude a mantener el control y la transparencia en tu aplicación Laravel!
Curso Laravel 12
Completo 2026
El único curso 100% actualizado que incluye Laravel 12, Livewire 3, Vue 3, React 19 e Inertia 2. Aprende con proyectos reales y las últimas funcionalidades.
star Incluido en cualquier suscripción