Modelos Eloquent
Eloquent es el ORM de Laravel que te permite trabajar con la base de datos usando clases PHP. Cada modelo representa una tabla y proporciona métodos intuitivos para consultar y manipular datos.
¿Qué es Eloquent?
Eloquent es un ORM (Object-Relational Mapping) que implementa el patrón Active Record. En lugar de escribir SQL directamente, trabajas con objetos PHP que representan filas de la base de datos.
Ventajas de usar Eloquent:
- Sintaxis elegante: Código más legible que SQL puro
- Independiente de la BD: Funciona con MySQL, PostgreSQL, SQLite, etc.
- Relaciones integradas: Define relaciones entre tablas fácilmente
- Protección automática: Previene inyección SQL
El modelo User
Laravel incluye un modelo
User por defecto en
app/Models/User.php:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
// El modelo asume que la tabla se llama 'users'
// y la clave primaria es 'id'
}
Por convención, Eloquent asume que el modelo
User corresponde a la tabla
users (nombre en plural y
minúsculas).
Crear un modelo
Para crear un nuevo modelo, usa el comando
make:model:
# Crear solo el modelo
php artisan make:model Post
# Crear modelo con migración
php artisan make:model Post -m
# Crear modelo con migración y controlador
php artisan make:model Post -mc
El modelo se crea en
app/Models/Post.php:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
//
}
Convenciones de nombres
Eloquent sigue convenciones para reducir la configuración necesaria:
-
Tabla: Plural del modelo en
snake_case (
Post→posts,BlogPost→blog_posts) -
Clave primaria:
id -
Timestamps:
created_atyupdated_at
Si tu tabla no sigue estas convenciones, puedes especificarlas:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
// Nombre de tabla personalizado
protected $table = 'blog_articles';
// Clave primaria diferente
protected $primaryKey = 'post_id';
// Desactivar timestamps
public $timestamps = false;
}
Fillable y guarded
Por seguridad, Eloquent protege contra la asignación masiva. Debes especificar qué campos se pueden rellenar:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
// Campos que se pueden asignar masivamente
protected $fillable = [
'title',
'slug',
'content',
'is_published',
];
}
Alternativamente, puedes usar
$guarded para especificar los
campos que NO se pueden asignar:
<?php
class Post extends Model
{
// Solo 'id' está protegido, el resto se puede asignar
protected $guarded = ['id'];
}
Un array vacío en
$guarded permite asignar
cualquier campo, incluyendo
id o is_admin.
Esto es un riesgo de seguridad.
Casting de atributos
Los datos de la base de datos se devuelven como strings. Puedes convertirlos automáticamente a tipos PHP:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
protected $fillable = [
'title',
'content',
'is_published',
'views',
'published_at',
];
protected function casts(): array
{
return [
'is_published' => 'boolean',
'views' => 'integer',
'published_at' => 'datetime',
];
}
}
El método casts() retorna un array
que define las conversiones de tipo. Tipos de
casting disponibles:
-
boolean- Convierte a true/false -
integer,float- Números string- Texto-
array,json- Convierte JSON a array PHP -
datetime,date- Objetos Carbon para fechas -
decimal:2- Decimal con precisión
Atributos ocultos
Cuando conviertes un modelo a JSON (por ejemplo, en una API), puedes ocultar campos sensibles:
<?php
class User extends Model
{
// Campos ocultos en JSON
protected $hidden = [
'password',
'remember_token',
];
// O especifica solo los visibles
protected $visible = [
'id',
'name',
'email',
];
}
Accessors y mutators
Los accessors modifican el valor al leerlo. Los mutators lo modifican al guardarlo:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
// Accessor: modifica al leer
protected function title(): Attribute
{
return Attribute::make(
get: fn (string $value) => ucfirst($value),
);
}
// Mutator: modifica al guardar
protected function slug(): Attribute
{
return Attribute::make(
set: fn (string $value) => strtolower(str_replace(' ', '-', $value)),
);
}
// Accessor y mutator combinados
protected function name(): Attribute
{
return Attribute::make(
get: fn (string $value) => ucwords($value),
set: fn (string $value) => strtolower($value),
);
}
}
Puedes crear atributos que no existen en
la base de datos. Por ejemplo, un
full_name que combine
first_name y
last_name.
Ejemplo completo
Veamos un modelo completo para un blog:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
class Article extends Model
{
protected $fillable = [
'user_id',
'title',
'slug',
'excerpt',
'content',
'is_published',
'published_at',
];
protected $hidden = [
'user_id',
];
protected function casts(): array
{
return [
'is_published' => 'boolean',
'published_at' => 'datetime',
];
}
// Accessor para el título
protected function title(): Attribute
{
return Attribute::make(
get: fn (string $value) => ucfirst($value),
);
}
// Atributo virtual: resumen automático
protected function summary(): Attribute
{
return Attribute::make(
get: fn () => $this->excerpt ?? substr($this->content, 0, 150) . '...',
);
}
}
Ejercicios
Ejercicio 1: Crear modelo Product
Crea un modelo Product con su
migración. El modelo debe tener como fillable:
name, sku, description, price, stock, is_active.
Añade casts para price (decimal:2), stock
(integer) e is_active (boolean).
Ver solución
# Crear modelo con migración
php artisan make:model Product -m
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
protected $fillable = [
'name',
'sku',
'description',
'price',
'stock',
'is_active',
];
protected function casts(): array
{
return [
'price' => 'decimal:2',
'stock' => 'integer',
'is_active' => 'boolean',
];
}
}
Ejercicio 2: Accessor para precio formateado
Añade al modelo Product un accessor
llamado formatted_price que
devuelva el precio con el símbolo del euro (ej:
"29,99 EUR").
Ver solución
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
protected $fillable = [
'name',
'sku',
'description',
'price',
'stock',
'is_active',
];
protected function casts(): array
{
return [
'price' => 'decimal:2',
'stock' => 'integer',
'is_active' => 'boolean',
];
}
protected function formattedPrice(): Attribute
{
return Attribute::make(
get: fn () => number_format($this->price, 2, ',', '.') . ' EUR',
);
}
}
<?php
// Uso:
$product = Product::find(1);
echo $product->formatted_price; // "29,99 EUR"
Ejercicio 3: Modelo con tabla personalizada
Crea un modelo Category que use la
tabla product_categories en lugar
de categories. La tabla no tiene
timestamps. Los campos fillable son: name, slug,
description.
Ver solución
# Crear el modelo
php artisan make:model Category
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
protected $table = 'product_categories';
public $timestamps = false;
protected $fillable = [
'name',
'slug',
'description',
];
}
Resumen
- Eloquent es el ORM de Laravel que implementa Active Record
-
Los modelos se crean con
php artisan make:model Nombre -
Por convención,
Postusa la tablaposts -
$fillabledefine qué campos se pueden asignar masivamente -
El método
casts()convierte atributos a tipos PHP (boolean, integer, datetime...) -
$hiddenoculta campos sensibles al convertir a JSON - Los accessors modifican valores al leer, los mutators al guardar
-
Usa
-mpara crear modelo con migración,-mcpara añadir controlador
¿Has encontrado un error o tienes una sugerencia para mejorar esta lección?
Escríbenos¿Te está gustando el curso?
Tenemos cursos premium con proyectos reales, soporte personalizado y certificado.
Descubrir cursos premium