5. Modelos en Laravel
¿Qué es un Modelo en Laravel?
Section titled “¿Qué es un Modelo en Laravel?”Un modelo en Laravel representa una tabla en la base de datos y actúa como una capa de abstracción que permite interactuar con los datos utilizando métodos y propiedades orientados a objetos. Laravel implementa el patrón Active Record a través de su ORM (Object-Relational Mapping) llamado Eloquent.
Cada modelo corresponde a una tabla específica en la base de datos y simplifica las operaciones comunes como:
- Crear, leer, actualizar y eliminar registros (CRUD)
- Definir relaciones entre tablas (one-to-one, one-to-many, many-to-many)
- Aplicar reglas de negocio a nivel de datos
- Realizar validaciones y transformaciones de datos
<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class User extends Model{ // Un modelo básico en Laravel}Crear un Modelo con Artisan (make:model)
Section titled “Crear un Modelo con Artisan (make:model)”Laravel proporciona el comando make:model en Artisan para generar rápidamente modelos:
php artisan make:model ProductEste comando creará un archivo Product.php en el directorio app/Models/.
Opciones comunes del comando make:model
Section titled “Opciones comunes del comando make:model”# Crear un modelo con migraciónphp artisan make:model Product -m
# Crear un modelo con controladorphp artisan make:model Product -c
# Crear un modelo con migración, factory, seeder y controladorphp artisan make:model Product -mfsc
# Crear un modelo con todo (migración, factory, seeder, controlador y policy)php artisan make:model Product --all
# Crear un modelo en un subdirectorio (namespace)php artisan make:model Admin/ProductUbicación y Convención de Nombres de Modelos
Section titled “Ubicación y Convención de Nombres de Modelos”Ubicación de los modelos
Section titled “Ubicación de los modelos”Por convención, los modelos se almacenan en el directorio app/Models/ (a partir de Laravel 8) o app/ (en versiones anteriores).
Convención de nombres
Section titled “Convención de nombres”- Los nombres de los modelos deben estar en singular y en PascalCase
- El nombre de la tabla correspondiente debe estar en plural y en snake_case
<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class Product extends Model // Nombre en singular y PascalCase{ // Laravel asumirá que la tabla se llama 'products' (plural y snake_case)}Asignación Masiva: $fillable y $guarded
Section titled “Asignación Masiva: $fillable y $guarded”La asignación masiva permite crear o actualizar un registro utilizando un array de datos. Para controlar qué atributos pueden ser asignados masivamente, Laravel ofrece dos propiedades: $fillable y $guarded.
Propiedad $fillable
Section titled “Propiedad $fillable”$fillable define una lista de atributos que están permitidos para asignación masiva (enfoque de lista blanca).
<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class Product extends Model{ /** * Los atributos que son asignables masivamente. * * @var array */ protected $fillable = [ 'name', 'description', 'price', 'category_id' ];
// Ahora podemos usar: // Product::create(['name' => 'Producto 1', 'price' => 99.99, ...]);}Propiedad $guarded
Section titled “Propiedad $guarded”$guarded define una lista de atributos que están protegidos contra la asignación masiva (enfoque de lista negra).
<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class Product extends Model{ /** * Los atributos que no son asignables masivamente. * * @var array */ protected $guarded = [ 'id', 'admin_flag' ];
// Todos los atributos excepto 'id' y 'admin_flag' serán asignables masivamente}Configuración de la Tabla Manual ($table)
Section titled “Configuración de la Tabla Manual ($table)”Si el nombre de tu tabla no sigue la convención de Laravel (plural del nombre del modelo), puedes especificarlo manualmente usando la propiedad $table:
<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class Product extends Model{ /** * El nombre de la tabla asociada con el modelo. * * @var string */ protected $table = 'inventory_products';
// Laravel usará la tabla 'inventory_products' en lugar de 'products'}Uso de Claves Primarias Personalizadas ($primaryKey)
Section titled “Uso de Claves Primarias Personalizadas ($primaryKey)”Por defecto, Laravel asume que cada tabla tiene una clave primaria llamada id. Si tu tabla utiliza un nombre diferente para la clave primaria, puedes especificarlo usando la propiedad $primaryKey:
<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class Product extends Model{ /** * La clave primaria asociada con la tabla. * * @var string */ protected $primaryKey = 'product_id';}Cambiar el tipo de clave primaria
Section titled “Cambiar el tipo de clave primaria”Si tu clave primaria no es un entero autoincremental, puedes especificar su tipo:
<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class ApiKey extends Model{ /** * La clave primaria asociada con la tabla. * * @var string */ protected $primaryKey = 'key';
/** * Indica si la clave primaria es autoincremental. * * @var bool */ public $incrementing = false;
/** * El tipo de dato de la clave primaria. * * @var string */ protected $keyType = 'string';}Activar o Desactivar Timestamps ($timestamps)
Section titled “Activar o Desactivar Timestamps ($timestamps)”Por defecto, Laravel mantiene automáticamente las columnas created_at y updated_at en tus tablas. Si no deseas utilizar estas columnas, puedes desactivarlas:
<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class Product extends Model{ /** * Indica si el modelo debe registrar timestamps. * * @var bool */ public $timestamps = false;}Personalizar los nombres de las columnas de timestamps
Section titled “Personalizar los nombres de las columnas de timestamps”Si utilizas nombres diferentes para las columnas de timestamps, puedes personalizarlos:
<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class Product extends Model{ /** * El nombre de la columna "created at". * * @var string */ const CREATED_AT = 'fecha_creacion';
/** * El nombre de la columna "updated at". * * @var string */ const UPDATED_AT = 'fecha_actualizacion';}Personalizar el formato de fecha
Section titled “Personalizar el formato de fecha”Puedes personalizar el formato de almacenamiento de los timestamps:
<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class Product extends Model{ /** * Prepara una fecha para el almacenamiento en la base de datos. * * @param DateTimeInterface $date * @return string */ protected function serializeDate(DateTimeInterface $date) { return $date->format('Y-m-d'); }}Definir Casts de Atributos ($casts)
Section titled “Definir Casts de Atributos ($casts)”Eloquent permite convertir automáticamente ciertos atributos a tipos de datos nativos de PHP cuando los recuperas del modelo, y viceversa cuando los almacenas en la base de datos.
<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class Product extends Model{ /** * Los atributos que deben ser convertidos a tipos nativos. * * @var array */ protected $casts = [ 'price' => 'float', 'active' => 'boolean', 'options' => 'array', 'released_at' => 'datetime', 'metadata' => 'json', 'dimensions' => 'object', 'sale_dates' => 'collection', ];}Tipos de casts disponibles
Section titled “Tipos de casts disponibles”integer/int: Convierte a enteroreal/float/double: Convierte a número de punto flotantestring: Convierte a cadena de textoboolean/bool: Convierte a booleanoobject: Convierte JSON a objeto PHP stdClassarray: Convierte JSON a array PHPcollection: Convierte JSON a una colección de Laraveljson: Convierte a JSON al guardar y de JSON al cargardatetime: Convierte a instancia Carbon/DateTimetimestamp: Convierte a timestamp Unixdate: Convierte a instancia Carbon con solo la fechaencrypted: Encripta/desencripta automáticamente los valoresdecimal:<precision>: Convierte a decimal con precisión específica (ej.decimal:2)
Cast personalizado
Section titled “Cast personalizado”Puedes crear tus propios casts personalizados:
<?php
namespace AppCasts;
use IlluminateContractsDatabaseEloquentCastsAttributes;
class Money implements CastsAttributes{ /** * Cast el valor dado. * * @param IlluminateDatabaseEloquentModel $model * @param string $key * @param mixed $value * @param array $attributes * @return mixed */ public function get($model, $key, $value, $attributes) { return new AppValueObjectsMoney($value / 100); }
/** * Prepara el valor dado para el almacenamiento. * * @param IlluminateDatabaseEloquentModel $model * @param string $key * @param mixed $value * @param array $attributes * @return mixed */ public function set($model, $key, $value, $attributes) { return [ $key => $value instanceof AppValueObjectsMoney ? $value->getAmount() * 100 : $value * 100, ]; }}Accesores y Mutadores
Section titled “Accesores y Mutadores”Los accesores y mutadores te permiten modificar los atributos cuando accedes a ellos o cuando los estableces en un modelo.
Accesores (get…Attribute)
Section titled “Accesores (get…Attribute)”Los accesores transforman los datos cuando los recuperas del modelo. Definen un formato de visualización sin alterar los datos almacenados en la base de datos.
<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class User extends Model{ /** * Obtiene el nombre del usuario en formato capitalizado. * * @param string $value * @return string */ public function getNameAttribute($value) { return ucfirst($value); }
/** * Obtiene el nombre completo del usuario. * * @return string */ public function getFullNameAttribute() { return "{$this->name} {$this->lastname}"; }}
// Uso:$user = User::find(1);echo $user->name; // Aplica el accesor automáticamenteecho $user->full_name; // Atributo virtual (no existe en la base de datos)<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;use IlluminateDatabaseEloquentCastsAttribute;
class User extends Model{ /** * Obtiene el nombre del usuario en formato capitalizado. * * @return IlluminateDatabaseEloquentCastsAttribute */ protected function name(): Attribute { return Attribute::make( get: fn ($value) => ucfirst($value), ); }
/** * Obtiene el nombre completo del usuario. * * @return IlluminateDatabaseEloquentCastsAttribute */ protected function fullName(): Attribute { return Attribute::make( get: fn () => "{$this->name} {$this->lastname}", ); }}
// Uso:$user = User::find(1);echo $user->name; // Aplica el accesor automáticamenteecho $user->full_name; // Atributo virtual (no existe en la base de datos)Mutadores (set…Attribute)
Section titled “Mutadores (set…Attribute)”Los mutadores transforman los datos antes de guardarlos en la base de datos:
<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class User extends Model{ /** * Establece el atributo de contraseña. * * @param string $value * @return void */ public function setPasswordAttribute($value) { $this->attributes['password'] = bcrypt($value); }
/** * Establece el atributo de email en minúsculas. * * @param string $value * @return void */ public function setEmailAttribute($value) { $this->attributes['email'] = strtolower($value); }}
// Uso:$user = new User;$user->password = 'password123'; // Se aplica el hash automáticamente$user->email = 'Usuario@EJEMPLO.com'; // Se convierte a minúsculas$user->save();<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;use IlluminateDatabaseEloquentCastsAttribute;
class User extends Model{ /** * Interactuar con la contraseña del usuario. * * @return IlluminateDatabaseEloquentCastsAttribute */ protected function password(): Attribute { return Attribute::make( set: fn ($value) => bcrypt($value), ); }
/** * Interactuar con el email del usuario. * * @return IlluminateDatabaseEloquentCastsAttribute */ protected function email(): Attribute { return Attribute::make( get: fn ($value) => $value, set: fn ($value) => strtolower($value), ); }}
// Uso:$user = new User;$user->password = 'password123'; // Se aplica el hash automáticamente$user->email = 'Usuario@EJEMPLO.com'; // Se convierte a minúsculas$user->save();Scopes Locales y Globales
Section titled “Scopes Locales y Globales”Los scopes te permiten encapsular lógica de consulta reutilizable.
Scopes Locales
Section titled “Scopes Locales”Los scopes locales permiten definir consultas reutilizables que pueden ser encadenadas con otras consultas:
<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;use IlluminateDatabaseEloquentBuilder;
class Product extends Model{ /** * Scope para productos activos. * * @param IlluminateDatabaseEloquentBuilder $query * @return IlluminateDatabaseEloquentBuilder */ public function scopeActive(Builder $query) { return $query->where('active', true); }
/** * Scope para productos en stock. * * @param IlluminateDatabaseEloquentBuilder $query * @return IlluminateDatabaseEloquentBuilder */ public function scopeInStock(Builder $query) { return $query->where('stock', '>', 0); }
/** * Scope para productos de una categoría específica. * * @param IlluminateDatabaseEloquentBuilder $query * @param int $categoryId * @return IlluminateDatabaseEloquentBuilder */ public function scopeByCategory(Builder $query, $categoryId) { return $query->where('category_id', $categoryId); }}
// Uso:$featuredProducts = Product::active()->inStock()->byCategory(1)->get();Scopes Globales
Section titled “Scopes Globales”Los scopes globales se aplican automáticamente a todas las consultas de un modelo:
<?php
namespace AppScopes;
use IlluminateDatabaseEloquentBuilder;use IlluminateDatabaseEloquentModel;use IlluminateDatabaseEloquentScope;
class ActiveScope implements Scope{ /** * Aplicar el scope a una consulta Eloquent. * * @param IlluminateDatabaseEloquentBuilder $builder * @param IlluminateDatabaseEloquentModel $model * @return void */ public function apply(Builder $builder, Model $model) { $builder->where('active', true); }}<?php
namespace AppModels;
use AppScopesActiveScope;use IlluminateDatabaseEloquentModel;
class Product extends Model{ /** * El método "booted" del modelo. * * @return void */ protected static function booted() { static::addGlobalScope(new ActiveScope); }}
// Todas las consultas ahora incluirán automáticamente WHERE active = true$products = Product::all();
// Para ignorar un scope global:$allProducts = Product::withoutGlobalScope(ActiveScope::class)->get();// O ignorar todos los scopes globales:$allProducts = Product::withoutGlobalScopes()->get();<?php
namespace AppModels;
use IlluminateDatabaseEloquentBuilder;use IlluminateDatabaseEloquentModel;
class Product extends Model{ /** * El método "booted" del modelo. * * @return void */ protected static function booted() { static::addGlobalScope('active', function (Builder $builder) { $builder->where('active', true); }); }}
// Para ignorar un scope global específico:$allProducts = Product::withoutGlobalScope('active')->get();Eventos del Modelo
Section titled “Eventos del Modelo”Los modelos Eloquent disparan eventos durante su ciclo de vida, lo que te permite ejecutar código cuando ocurren acciones específicas.
Eventos disponibles
Section titled “Eventos disponibles”retrieved: Después de que un modelo es recuperado de la base de datoscreating: Antes de que un nuevo modelo sea guardado por primera vezcreated: Después de que un nuevo modelo ha sido guardado por primera vezupdating: Antes de guardar un modelo existenteupdated: Después de guardar un modelo existentesaving: Antes de guardar un modelo (nuevo o existente)saved: Después de guardar un modelo (nuevo o existente)deleting: Antes de eliminar un modelodeleted: Después de eliminar un modelotrashed: Después de que un modelo ha sido marcado como eliminado (soft delete)forceDeleting: Antes de eliminar permanentemente un modeloforceDeleted: Después de eliminar permanentemente un modelorestoring: Antes de restaurar un modelo eliminado (soft delete)restored: Después de restaurar un modelo eliminado (soft delete)
Registrar eventos utilizando observers
Section titled “Registrar eventos utilizando observers”<?php
namespace AppObservers;
use AppModelsUser;use IlluminateSupportFacadesLog;
class UserObserver{ /** * Manejar el evento "created" del modelo. * * @param AppModelsUser $user * @return void */ public function created(User $user) { Log::info('Se ha creado un nuevo usuario: ' . $user->name); }
/** * Manejar el evento "updated" del modelo. * * @param AppModelsUser $user * @return void */ public function updated(User $user) { Log::info('El usuario ha sido actualizado: ' . $user->name); }
/** * Manejar el evento "deleted" del modelo. * * @param AppModelsUser $user * @return void */ public function deleted(User $user) { Log::info('El usuario ha sido eliminado: ' . $user->name); }}<?php
namespace AppProviders;
use AppModelsUser;use AppObserversUserObserver;use IlluminateSupportServiceProvider;
class AppServiceProvider extends ServiceProvider{ /** * Inicializa los servicios de la aplicación. * * @return void */ public function boot() { // Registrar el observer User::observe(UserObserver::class); }}Eventos directamente en el modelo
Section titled “Eventos directamente en el modelo”<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;use IlluminateSupportFacadesLog;
class User extends Model{ /** * El método "booted" del modelo. * * @return void */ protected static function booted() { // Usando closures para los eventos static::created(function ($user) { Log::info('Nuevo usuario creado: ' . $user->name); });
static::updated(function ($user) { Log::info('Usuario actualizado: ' . $user->name); });
static::deleted(function ($user) { Log::info('Usuario eliminado: ' . $user->name); }); }}Métodos Útiles de Modelo
Section titled “Métodos Útiles de Modelo”Los modelos Eloquent ofrecen una variedad de métodos útiles para operaciones comunes.
Operaciones con Registros
Section titled “Operaciones con Registros”<?php
// Crear una instancia sin guardar$user = new User;$user->name = 'Nuevo Usuario';$user->email = 'usuario@ejemplo.com';
// Guardar la instancia en la base de datos$user->save();
// Crear una instancia y guardarla de inmediato$user = User::create([ 'name' => 'Nuevo Usuario', 'email' => 'usuario@ejemplo.com', 'password' => bcrypt('password'),]);
// Actualizar un modelo existente$user = User::find(1);$user->email = 'nuevo_email@ejemplo.com';$user->save();
// Actualizar múltiples atributos a la vez$user->update([ 'name' => 'Nombre Actualizado', 'email' => 'email_actualizado@ejemplo.com',]);
// Actualizar o crear un registro$user = User::updateOrCreate( ['email' => 'usuario@ejemplo.com'], // atributos de búsqueda ['name' => 'Actualizado', 'active' => true] // atributos para actualizar o crear);
// Borrar un modelo$user->delete();
// Borrar por IDUser::destroy(1);User::destroy([1, 2, 3]); // múltiples IDs
// Usar soft deletes (requiere columna deleted_at y trait SoftDeletes)$user->delete(); // marca como eliminado$user->trashed(); // verifica si está eliminado$user->forceDelete(); // elimina permanentemente
// Restaurar un modelo eliminado con soft delete$user->restore();
// Actualizar un contador directamente en la base de datosPost::find(1)->increment('view_count');Post::find(1)->increment('view_count', 5); // incrementar por 5Product::find(1)->decrement('stock');
// Refrescar datos del modelo desde la base de datos$user->refresh();
// Replicar un modelo (clonar sin ID)$clonedUser = $user->replicate();$clonedUser->save();Métodos de Comparación
Section titled “Métodos de Comparación”<?php
// Comprobar si dos modelos son el mismo registro en base de datos$user->is($anotherUser); // true si tienen el mismo ID y tabla
// Comprobar si un modelo ha cambiado desde su carga$user->isDirty(); // true si hay cambios sin guardar$user->isDirty('email'); // true si el email ha cambiado
// Comprobar si un modelo NO ha sido modificado$user->isClean();$user->isClean('name');
// Comprobar si un atributo específico ha cambiado$user->wasChanged();$user->wasChanged('email');
// Obtener atributos originales (antes de cambios)$originalEmail = $user->getOriginal('email');$allOriginal = $user->getOriginal(); // todos los valores originalesRelaciones entre Modelos
Section titled “Relaciones entre Modelos”Eloquent permite definir relaciones entre modelos de forma elegante y expresiva.
Tipos de Relaciones
Section titled “Tipos de Relaciones”Los principales tipos de relaciones en Laravel son:
1. Uno a Uno (One-to-One)
Section titled “1. Uno a Uno (One-to-One)”<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class User extends Model{ /** * Obtiene el perfil asociado con el usuario. */ public function profile() { return $this->hasOne(Profile::class);
// Con claves personalizadas: // return $this->hasOne(Profile::class, 'user_id', 'id'); }}
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class Profile extends Model{ /** * Obtiene el usuario al que pertenece este perfil. */ public function user() { return $this->belongsTo(User::class);
// Con claves personalizadas: // return $this->belongsTo(User::class, 'user_id', 'id'); }}
// Uso:$profile = User::find(1)->profile;$user = Profile::find(1)->user;2. Uno a Muchos (One-to-Many)
Section titled “2. Uno a Muchos (One-to-Many)”<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class Post extends Model{ /** * Obtiene los comentarios asociados con el post. */ public function comments() { return $this->hasMany(Comment::class); }}
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class Comment extends Model{ /** * Obtiene el post al que pertenece el comentario. */ public function post() { return $this->belongsTo(Post::class); }}
// Uso:$comments = Post::find(1)->comments; // Colección de comentarios$post = Comment::find(1)->post;
// Contar relaciones$postWithCommentCount = Post::withCount('comments')->get();echo $postWithCommentCount[0]->comments_count;3. Muchos a Muchos (Many-to-Many)
Section titled “3. Muchos a Muchos (Many-to-Many)”<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class User extends Model{ /** * Los roles que pertenecen al usuario. */ public function roles() { return $this->belongsToMany(Role::class);
// Con tabla pivot personalizada: // return $this->belongsToMany(Role::class, 'user_roles');
// Con claves personalizadas: // return $this->belongsToMany(Role::class, 'user_roles', 'user_id', 'role_id');
// Con columnas adicionales en la tabla pivot: // return $this->belongsToMany(Role::class)->withPivot('active', 'created_by');
// Con timestamps en la tabla pivot: // return $this->belongsToMany(Role::class)->withTimestamps(); }}
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class Role extends Model{ /** * Los usuarios que pertenecen al rol. */ public function users() { return $this->belongsToMany(User::class); }}
// Uso:$roles = User::find(1)->roles;$users = Role::find(1)->users;
// Adjuntar y separar relaciones$user = User::find(1);$user->roles()->attach(1); // Añadir un rol$user->roles()->attach([1, 2, 3]); // Añadir varios roles$user->roles()->attach(1, ['expires_at' => now()->addDays(30)]); // Con datos pivot
$user->roles()->detach(1); // Quitar un rol$user->roles()->detach(); // Quitar todos los roles
$user->roles()->sync([1, 2]); // Sincronizar (solo mantiene los roles 1 y 2)$user->roles()->syncWithoutDetaching([1, 2, 3]); // Añade solo los que faltan
// Acceso a la tabla pivot$user = User::find(1);foreach ($user->roles as $role) { echo $role->pivot->created_at;}4. Uno a Muchos a Través (Has Many Through)
Section titled “4. Uno a Muchos a Través (Has Many Through)”<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class Country extends Model{ /** * Obtiene todos los post de los usuarios de este país. */ public function posts() { return $this->hasManyThrough( Post::class, // Modelo final User::class // Modelo intermedio // 'user_id', // Clave externa en el modelo intermedio (opcional) // 'country_id', // Clave externa en el modelo final (opcional) // 'id', // Clave local en este modelo (opcional) // 'id' // Clave local en el modelo intermedio (opcional) ); }}
// Uso:$posts = Country::find('ES')->posts;5. Polimórficas
Section titled “5. Polimórficas”<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class Image extends Model{ /** * Obtiene el modelo al que pertenece esta imagen. */ public function imageable() { return $this->morphTo(); }}
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class User extends Model{ /** * Obtiene la imagen del usuario. */ public function image() { return $this->morphOne(Image::class, 'imageable'); }}
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class Post extends Model{ /** * Obtiene la imagen del post. */ public function image() { return $this->morphOne(Image::class, 'imageable'); }}
// Uso:$imageOfUser = User::find(1)->image;$ownerModel = Image::find(1)->imageable; // Puede ser User o PostClases Base y Traits
Section titled “Clases Base y Traits”Los modelos de Laravel heredan una rica funcionalidad de clases base y traits.
Clase Base - Illuminate\Database\Eloquent\Model
Section titled “Clase Base - Illuminate\Database\Eloquent\Model”Todos los modelos de Laravel extienden esta clase base, que proporciona:
- Operaciones CRUD básicas
- Construcción de consultas
- Sistema de eventos
- Conversión de atributos
- Serialización
Traits Comunes
Section titled “Traits Comunes”HasFactory
Section titled “HasFactory”Proporciona el método factory() para crear instancias de prueba:
<?php
namespace AppModels;
use IlluminateDatabaseEloquentFactoriesHasFactory;use IlluminateDatabaseEloquentModel;
class User extends Model{ use HasFactory;}
// Uso en pruebas o en seeders:User::factory()->count(50)->create();SoftDeletes
Section titled “SoftDeletes”Para implementar la eliminación suave (marcar como eliminados sin borrar):
<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;use IlluminateDatabaseEloquentSoftDeletes;
class Post extends Model{ use SoftDeletes;
// La tabla debe tener una columna deleted_at nullable}
// Uso:$post->delete(); // Marca como eliminado (actualiza deleted_at)
// Consulta sólo registros no eliminados (comportamiento por defecto)$activePosts = Post::all();
// Incluir registros eliminados$allPosts = Post::withTrashed()->get();
// Sólo registros eliminados$deletedPosts = Post::onlyTrashed()->get();
// Restaurar registros eliminados$post->restore();Post::onlyTrashed()->restore(); // Restaurar todos
// Eliminar permanentemente$post->forceDelete();Otros Traits Útiles
Section titled “Otros Traits Útiles”- HasAttributes: Maneja conversiones de atributos y accesores/mutadores
- Notifiable: Para enviar notificaciones a un modelo
- Cacheable: Para implementar caché en las consultas de modelos
- Auditable: Para registrar cambios en los modelos
- Searchable: Para búsqueda de texto completo en Laravel Scout