Eloquent en Laravel 8: las funciones principales del ORM

Eloquent en Laravel 8: las funciones principales del ORM
Eloquent, que viene incluido en el famoso framework PHP Laravel, ofrece una forma elegante y muy eficaz de comunicarse con la base de datos. Los sitios web son cada vez más complejos por la cantidad de personalizaciones, y eso obliga a diseñar bases de datos igual de complejas. Eloquent simplifica ese trabajo: te deja escribir código bien formateado, fácil de leer, mantenible y bien documentado. Con tantas funciones a mano, es una de las razones del éxito de Laravel.En este artículo repasamos algunas de las funciones más importantes de Eloquent ORM.

¿Qué es Eloquent ORM?

Eloquent ORM se distribuye con el framework Laravel para trabajar con la base de datos de forma sencilla y sin complicaciones. Algunas de las funciones que le han dado fama son el soft delete, los timestamps, la implementación de ActiveRecord, la gestión de varias bases de datos, el eager loading, los observers de modelo, los eventos de modelo y muchas más. Las relaciones de Eloquent son métodos de las clases de modelo. Definidas como métodos, son potentes query builders: puedes encadenar llamadas y construir consultas muy expresivas.

¿Cómo funciona Eloquent ORM?

Eloquent ORM es conocido por su implementación de Active Record para trabajar con bases de datos. Active Record es un patrón arquitectónico en el que cada modelo de la arquitectura MVC corresponde a una tabla de la base de datos. Con Eloquent creas relaciones entre tus datos y trabajas con un modelo orientado a objetos sin esfuerzo. Escribir consultas SQL a mano es tedioso y lento, Eloquent te permite hacer las operaciones habituales sin largas sentencias SQL. Los modelos han vuelto triviales la inserción, la actualización, el borrado y la sincronización entre varias bases de datos. Solo tienes que definir las tablas y la relación entre ellas, y ya está.

Empezar con Eloquent

Laravel incluye una interfaz de línea de comandos integrada, la consola Artisan. Está construida sobre el componente Console de Symfony y facilita el trabajo desde la terminal durante la fase de desarrollo.

Antes de seguir, configura la conexión a la base de datos en el archivo config/database.php.

Antes de usar el modelo Eloquent, comprueba que tienes Laravel instalado. Si todavía no lo tienes, puedes descargarlo desde getcomposer.org

Para ver la lista de comandos disponibles en Artisan, escribe lo siguiente:

bash
php artisan list

Verás en pantalla todos los comandos con una breve descripción. Si necesitas ayuda sobre alguno, basta con escribirlo precedido de «help». Por ejemplo:

bash
php artisan help migrate

Crear modelos Eloquent

Antes de nada tienes que crear un modelo en la base de datos. Los modelos te ayudan con el seeding, las migraciones y demás, son ellos los que hablan con la base de datos. También te permiten consultarla y poblarla con datos. El modelo se guarda normalmente en App\Models por claridad y para mantener el código bien documentado. Nosotros preferimos esa práctica, pero la elección es tuya: la única condición es que la clase se cargue automáticamente según tu archivo composer.json. Todos los modelos Eloquent extienden la clase Illuminate\Database\Eloquent\Model. El comando básico para crear modelos es el comando `make:model` de Artisan:

bash
php artisan make: model Student

La sintaxis básica para definir un modelo es:

php
class User extends Model {}

La migración de la base de datos también se puede generar al crear el modelo: basta con añadir `-m` o `-migration` al comando anterior.

bash
php artisan make:model Student--migration
php artisan make:model Flight -m

Los seeders, las factories, los controladores y otros tipos de clase se generan pasando los parámetros adecuados al comando `make:model` de Artisan. Aquí tienes algunos ejemplos:

bash
php artisan make:model Flight --factory
php artisan make:model Flight -f

php artisan make:model Flight --seed
php artisan make:model Flight -s

php artisan make:model Flight --controller
php artisan make:model Flight -c

Además, estos parámetros se pueden combinar para crear varias clases de una sola vez.

bash
php artisan make:model Flight -mfsc

Algunas convenciones básicas de los modelos que conviene tener en mente:

  • Nombre de la tabla: por convención, el nombre de la tabla es el nombre del modelo en plural y en minúsculas. Por ejemplo, si el modelo se llama Student, la tabla debería llamarse students. Si el nombre del modelo tiene varias palabras, se separan con guion bajo.
  • Clave primaria: Eloquent asume que la clave primaria es el atributo id. Puedes cambiar ese comportamiento con `$primaryKey`.
  • Timestamp: por defecto, `created_at` y `updated_at` los gestiona Eloquent automáticamente. Si no quieres esa gestión automática, pon `$timestamp` a false. Y si quieres personalizar el formato de fecha y hora, usa la propiedad `$dateFormat` de tu modelo.

Actualizar y eliminar elementos

Actualizar

Para actualizar un modelo tienes que recuperarlo, modificar el atributo que quieras cambiar y llamar al método save. El campo `updated_at` se actualiza solo, así que no hace falta tocarlo a mano.

php
$student = Student::find(1);

$student->email = ‘xyz@example.com';

$student>save();

Las actualizaciones masivas también se pueden hacer sobre todos los modelos que coincidan con una consulta.

Eliminar un modelo existente

Para borrar un modelo basta con llamar al método delete:

php
$student = Student::find(1);

$student>delete();

Borrado por clave:

php
Student::destroy(1);

Student::destroy([1, 2, 3]);

Student::destroy(1, 2, 3);

También puedes borrar a partir de una consulta.

php
$affectedRows = Student::where('votes', '>', 100)->delete();

Modelos relacionados

En cualquier base de datos puede haber modelos relacionados. Cuando dos o más modelos dependen unos de otros para su valor, se habla de modelos relacionados. Por ejemplo, si quieres añadir un comentario nuevo a un post, en lugar de rellenar el campo post_id a mano, puedes crearlo directamente desde el modelo padre

php
$comment = new Comment(['message' => 'A new comment.']);

$post = Post::find(1);

$comment = $post->comments()->save($comment);

Modelos asociados

Estos modelos se actualizan con el método associate, que fija una clave foránea en el modelo. También puedes asociar modelos que tengan varias relaciones.

Eventos de modelo

Cada vez que un modelo pasa por una etapa de su ciclo de vida (guardado, actualización o borrado) se dispara un evento de modelo. Los eventos disponibles son saved, deleted, updating, deleting, updated, restoring y restored. Por ejemplo, al insertar un elemento nuevo se dispara creating/created, si el elemento ya existía, se dispara updating/updated.

Cancelar el guardado desde un evento

Si el evento devuelve false, la acción se cancela. Sirve con cualquier evento: borrado, actualización, creación o guardado.

php
Student::creating(function($student)
{
    if ( ! $student>isValid()) return false;
});

Cómo registrar listeners de eventos

Como en cualquier lenguaje, un evento necesita un service provider para registrarse. Aquí ocurre lo mismo: los listeners se registran en EventServiceProvider que es el sitio previsto para declarar los bindings de eventos de modelo.

Ejemplo:

php
public function boot(DispatcherContract $events)
{
    parent::boot($events);

Student::creating(function($student)
    {
        //
    });
}

Observers de modelo

Los observers de modelo ayudan a gestionar los eventos de modelo. Una clase observer puede tener métodos que se corresponden con los distintos eventos.

php
class StudentObserver {

public function saving($model)
    {
        //
    }

public function saved($model)
    {
        //
    }

}

Otra forma de registrar un observer es con el método observe

php
User::observe(new UserObserver);

Generar URLs a partir de un modelo

Las URLs de modelo se construyen pasando el modelo al método route o action. Cuando le pasas un modelo, su clave primaria se inserta en la URI.

php
Route::get('student/{student}', 'StudentController@show');

action('StudentController@show', [$student]);

Aquí se insertará en la URL el identificador del estudiante. Si prefieres usar otra propiedad en la URL generada, sobrescribe el método getRouteKey en tu modelo.

php
public function getRouteKey()
{
    return $this->slug;
}

Más funciones de Eloquent en Laravel

Convertir a array o a JSON

Cuando construyes una API el resultado suele ir en JSON, así que tienes que convertir tus relaciones a JSON o a array. Eloquent también cubre esa necesidad. Para convertir a array las relaciones de un modelo, tienes el método toArray().

php
$student = Student::with('roles')->first();

return $student->toArray();

Para convertir a array una colección entera, puedes usar estos métodos:

php
return Student::find(1)->toJson();

Veamos ahora cómo devolver un modelo desde una ruta. Cada vez que un modelo se convierte a cadena se convierte a JSON, así que puedes devolver objetos Eloquent directamente desde las rutas.

php
Route::get('student', function()
{
    return Student::all();
});

Algunos campos sensibles como `personal_id` o la contraseña tienen que quedar ocultos. Para eso hay que declarar `$hidden` en tu modelo,

Casting de atributos

Si quieres convertir el tipo de dato de un atributo, una opción es escribir un mutador para cada uno, lo que lleva tiempo y acaba generando bugs. La otra opción es aplicar un cast a ese atributo: basta con añadirlo a la propiedad casts de tu modelo. Los tipos de cast admitidos son integer, float, double, real, object, string, array.

Aquí tienes un ejemplo.

php
protected $casts = [
    'is_student' => 'boolean',
];

En este ejemplo, aunque is_student tenga otro tipo de dato en la base de datos, al leerlo lo recibirás como un booleano.

El cast a array resulta muy útil cuando trabajas con una columna que guarda JSON serializado. Serializar en JSON significa codificar un objeto en una cadena. Si una de tus columnas contiene JSON serializado, el cast a array lo convertirá automáticamente en un array de PHP al leerlo desde el modelo Eloquent.

php
protected $casts = [
    'options' => 'array',
];

Mutadores de fecha

Carbon es una extensión de la clase DateTime de PHP. Eloquent convierte created_at y updated_at en instancias de Carbon, que aporta un montón de métodos útiles sobre DateTime. Si no quieres esa conversión automática, personalizarla es sencillo: basta con sobrescribir el método getDates de tu modelo. Para desactivar por completo la conversión de fechas, devuelve un array vacío en el método `getDates` . Aquí tienes un ejemplo:

php
public function getDates()
{
    return ['created_at'];
}

Si una columna se trata como una fecha, tienes cuatro posibilidades: un timestamp UNIX, una cadena de fecha (Y-m-d), una fecha y hora, o una instancia de DateTime o de Carbon.

Accesores y mutadores

Igual que se leen y se escriben valores en cualquier lenguaje, los accesores y los mutadores permiten formatear los atributos de Eloquent antes de leerlos o de asignarlos en las instancias del modelo. La diferencia está en el sentido: los accesores sirven para recuperar los datos, mientras que los mutadores se encargan de modificarlos.

Para definir un accesor basta con declarar `getFooAttribute` en tu modelo, respetando el camelCase del nombre del método aunque la columna esté en minúsculas.

php
class User extends Model {

public function getFirstNameAttribute($value)
    {
        return ucfirst($value);
    }

}

Un mutador se define de la misma forma: usa `setFooAttribute` y, otra vez, respeta el camelCase.

php
class User extends Model {

public function setFirstNameAttribute($value)
    {
        $this->attributes['first_name'] = strtolower($value);
    }

}

Soft delete

El soft delete no borra la fila de la base de datos, sino que rellena un timestamp aparte. La columna `deleted_at` se añade al registro correspondiente. Para activarlo en tu modelo, aplícale el trait SoftDeletes.

php
use Illuminate\Database\Eloquent\SoftDeletes;

class User extends Model {

use SoftDeletes;

protected $dates = ['deleted_at'];

}

softDeletes() sirve para añadir la columna deleted_at desde la migración. Una migración no es más que gestionar la base de datos en PHP en lugar de en SQL.

php
$table->softDeletes();

En algunos casos querrás ver también los registros borrados en soft delete al lanzar una consulta. Para eso tienes withTrashed() en la consulta.

Si solo quieres ver los modelos borrados en soft delete, usa el método onlyTrashed() en la consulta.

php
$student = Student::onlyTrashed()->where('account_id', 1)->get();

Después de tantas operaciones, si quieres devolver al estado activo un modelo borrado en soft delete, usa el método restore.

php
$student->restore();

restore() también se puede usar directamente en la consulta.

php
Student::withTrashed()->where('account_id', 1)->restore();

Y si después del soft delete quieres borrar el modelo definitivamente de la base de datos, usa el método forceDelete().

php
$student->posts()->forceDelete();

Para comprobar si un modelo está borrado o no, tienes el método trashed().

php
if ($student->trashed())
{
    //Todo
}

Conclusión

Laravel es uno de los frameworks más conocidos de PHP, y Eloquent hace que comunicarse con la base de datos sea muy sencillo. En este artículo hemos repasado algunas de sus funciones más importantes. Hay muchas más, y puedes conocerlas aquí. Sigue el enlace y descubre todo lo que ofrece Eloquent.


LaravelPHP

Damien Flandrin Desarrollador web desde 2010, creador de Gekkode y de Email Impact. Cada artículo se prueba en un proyecto real antes de publicarse. Contacto
Newsletter

Las nuevas pruebas, tutoriales y proyectos, por correo.

Pruebas reproducibles, código versionado, resultados fechados. Nunca spam.