⛩️ El Corazón de Laravel
Eloquent es el ORM de Laravel que transforma la interacción con bases de datos en poesía. Cada tabla es un modelo, cada relación es una conexión viva.
🎯 Definición Teórica: El Por Qué de Eloquent
Filosofía
Tabla Users → Modelo User
---------------------------------
id → $user->id
name → $user->name
email → $user->email
created_at → $user->created_at
El Problema que Resuelve
| Sin Eloquent | Con Eloquent |
|---|---|
| 50+ líneas de SQL | 1 línea de código |
| Consultas inseguras | Inyección SQL imposible |
| Arrays asociativos | Objetos tipados |
| Relaciones manuales | Métodos mágicos |
🗡️ Guía de Implementación
1. Modelo Básico
<?php
// app/Models/User.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
// Tabla (opcional si sigue convención)
protected $table = 'users';
// Primary key
protected $primaryKey = 'id';
// Timestamps automáticos
public $timestamps = true;
// Columns que pueden ser asignadas masivamente
protected $fillable = [
'name',
'email',
'password',
'role'
];
// Columns que no pueden ser asignadas masivamente
protected $hidden = [
'password',
'remember_token'
];
// Casts automáticos
protected $casts = [
'email_verified_at' => 'datetime',
'is_admin' => 'boolean',
'settings' => 'array'
];
}
2. Relaciones (El Poder de Eloquent)
// ╔═══════════════════════════════════════════════════════════════╗
// ║ TIPOS DE RELACIONES ║
// ╠══════════════════════════════╦═════════════════════════════════╣
// ║ One to One (hasOne) ║ Usuario → Perfil ║
// ║ One to Many (hasMany) ║ Usuario → Publicaciones ║
// ║ Many to Many (belongsToMany) ║ Usuario ←→ Roles ║
// ║ Has One Through ║ Usuario → Teléfono (país) ║
// ║ Has Many Through ║ País → Ciudades → Usuarios ║
// ╚══════════════════════════════╩═══════════════════════════════════╝
One to One
// Modelo User
public function perfil() {
return $this->hasOne(Perfil::class);
}
// Modelo Perfil
public function usuario() {
return $this->belongsTo(User::class);
}
// Uso
$usuario = User::find(1);
$perfil = $usuario->perfil;
One to Many
// Modelo User
public function publicaciones() {
return $this->hasMany(Publicacion::class);
}
// Modelo Publicacion
public function autor() {
return $this->belongsTo(User::class, 'user_id');
}
// Uso
$publicaciones = User::find(1)->publicaciones;
Many to Many
// Modelos: User y Rol
// Tabla pivote: role_user (o alphabetico: rol_user)
// Modelo User
public function roles() {
return $this->belongsToMany(Rol::class);
}
// Modelo Rol
public function usuarios() {
return $this->belongsToMany(User::class);
}
// Uso
$user = User::find(1);
$user->roles()->attach(1); // Agregar rol
$user->roles()->detach(1); // Quitar rol
$user->roles()->sync([1, 2, 3]); // Sincronizar roles
// Con timestamps
$user->roles()->attach(1, ['expira_en' => now()->addYear()]);
3. Consultas Avanzadas
// ╔═══════════════════════════════════════════════════════════════╗
// ║ MÉTODOS DE CONSULTA ║
// ╠═══════════════════════════════════════════════════════════════╣
// ║ all() ║ Obtener todos ║
// ║ find($id) ║ Buscar por ID ║
// ║ findOrFail($id) ║ Buscar o lanzar 404 ║
// ║ first() ║ Primer resultado ║
// ║ firstOrFail() ║ Primero o 404 ║
// ║ get() ║ Colección ║
// ║ pluck('columna') ║ Solo una columna ║
// ║ count() ║ Contar resultados ║
// ║ exists() ║ Verificar existencia ║
// ╚═══════════════════════════════════════════════════════════════╝
// Where avanzado
$usuarios = User::where('email', 'like', '%@gmail.com')
->whereBetween('created_at', ['2024-01-01', '2024-12-31'])
->orWhere('role', 'admin')
->orderBy('name')
->limit(10)
->get();
// Chunk para grandes cantidades
User::chunk(100, function ($usuarios) {
foreach ($usuarios as $usuario) {
// Procesar 100 usuarios a la vez
}
});
4. Scopes (Alcances)
// En el modelo User
class User extends Model
{
// Scope local (requiere 'scope' prefix)
public function scopeActivos($query) {
return $query->where('activo', true);
}
public function scopeAdmin($query) {
return $query->where('role', 'admin');
}
public function scopeCreadoEntre($query, $inicio, $fin) {
return $query->whereBetween('created_at', [$inicio, $fin]);
}
// Scope con parámetros
public function scopeRol($query, $rol) {
return $query->where('role', $rol);
}
}
// Uso
$admins = User::activos()->admin()->get();
$usuarios = User::rol('editor')->creadoEntre('2024-01-01', '2024-06-30')->get();
5. Accessors y Mutators
class User extends Model
{
// ACCESSOR: Transformar al LEER
public function getNombreCompletoAttribute() {
return ucfirst($this->name) . ' ' . ucfirst($this->apellido);
}
// MUTATOR: Transformar al ESCRIBIR
public function setEmailAttribute($value) {
$this->attributes['email'] = strtolower($value);
}
public function setPasswordAttribute($value) {
$this->attributes['password'] = bcrypt($value);
}
}
// Uso
$user = User::find(1);
echo $user->nombreCompleto; // "Juan Pérez"
$user->email = 'JUAN@EJEMPLO.COM';
$user->save();
// Se guarda como 'juan@ejemplo.com'
🥷 Reto Ninja
Nivel: Jonin
Misión 1: Crea un Blog Completo
// Modelos y relaciones para un blog
// Post.php
class Post extends Model
{
protected $fillable = ['title', 'content', 'user_id', 'category_id', 'published'];
public function autor() {
return $this->belongsTo(User::class);
}
public function categoria() {
return $this->belongsTo(Category::class);
}
public function comentarios() {
return $this->hasMany(Comentario::class);
}
public function etiquetas() {
return $this->belongsToMany(Etiqueta::class);
}
// Scope para posts publicados
public function scopePublicado($query) {
return $query->where('published', true)
->where('published_at', '<=', now());
}
}
Misión 2: Eager Loading Completo
// Obtener posts con todas sus relaciones
$posts = Post::publicado()
->with(['autor', 'categoria', 'comentarios.usuario', 'etiquetas'])
->withCount('comentarios')
->orderBy('published_at', 'desc')
->get();
// Con relaciones anidadas
// Post → Comentario → Usuario (autor del comentario)
Misión 3: Colecciones
$usuarios = User::all();
// Métodos de colección
$emails = $usuarios->pluck('email');
$nombres = $usuarios->pluck('name', 'id'); // [1 => 'Juan', 2 => 'María]
$primero = $usuarios->first();
$ultimo = $usuarios->last();
$admins = $usuarios->filter(function ($user) {
return $user->role === 'admin';
});
$sinEmail = $usuarios->reject(function ($user) {
return $user->email;
});
📜 Métodos Mágicos
// Crear con relaciones
$post = Post::create([
'title' => 'Nuevo Post',
'content' => 'Contenido...',
'user_id' => 1
]);
// Relacionar automáticamente
$post->autor()->associate(User::find(1));
$post->save();
// Attach/Detach en many-to-many
$post->etiquetas()->attach([1, 2, 3]);
$post->etiquetas()->detach(1);
$post->etiquetas()->sync([2, 3, 4]);
🎓 Conclusión del Maestro
“Eloquent no es solo una herramienta, es una forma de pensar. Representa tus datos como objetos vivos, y las relaciones fluyen como el chakra.” — Maestro de Laravel
✅ Checklist de Dominio
- Crear modelo con todas las relaciones
- Implementar CRUD completo
- Dominar scopes locales
- Usar accessors y mutators
- Implementar eager loading
- Manejar relaciones many-to-many
Recompensa XP: 100 XP ⚔️