RELACIONES CON ELOQUENT EN LARAVEL
Las relaciones en Eloquent son una de las características más potentes del ORM de Laravel. Permiten definir cómo se relacionan los modelos (tablas de la base de datos) de forma limpia, sin tener que escribir "joins" manuales todo el tiempo. En lugar de hacer consultas SQL complejas, simplemente usas métodos como "$user->posts" o "$post->user" y Eloquent se encarga de todo. Las relaciones en Eloquent convierten esto:SELECT * FROM posts WHERE user_id = 1;
$user->posts
Tipos principales de relaciones en Eloquent
Ejemplos
- One to One (Uno a Uno). Un modelo tiene exactamente una relación con otro.
// User.php public function profile() { return $this->hasOne(Profile::class); } // Profile.php public function user() { return $this->belongsTo(User::class); } //En el controlador $user = User::find($id); $profile = $user->profile; // acceso directo a la relación return response()->json($profile); - One to Many (Uno a Muchos). Un registro de una tabla puede estar relacionado con MUCHOS registros de otra tabla.
// Modelo User.php public function posts() { return $this->hasMany(Post::class); // un usuario tiene muchos posts } // Modelo Post.php public function user() { return $this->belongsTo(User::class); // un post pertenece a un usuario } //uso (en el controlador) $user = User::find(1); $posts = $user->posts; // devuelve colección de posts $post = Post::find(5); $autor = $post->user; - Many to Many (Muchos a Muchos). Un registro de la tabla A puede estar relacionado con muchos registros de la tabla B.Y al mismo tiempo, un registro de la tabla B puede estar relacionado con muchos registros de la tabla A.
// User.php public function roles() { return $this->belongsToMany(Role::class) ->withPivot('active') // si quieres datos de la tabla pivote ->withTimestamps(); } // Role.php public function users() { return $this->belongsToMany(User::class); } //uso (en el controlador) $user->roles()->attach(2); // asignar rol $user->roles()->sync([1, 3, 5]); // reemplazar todos - Has Many Through (Acceder a través de una tabla intermedia). Un País tiene muchos Usuarios, y cada Usuario tiene muchos Posts.
Quieres obtener todos los Posts de un País directamente sin pasar por los usuarios.
.
// countries table $table->id(); $table->string('name'); // users table $table->id(); $table->foreignId('country_id')->constrained(); $table->string('name'); // posts table $table->id(); $table->foreignId('user_id')->constrained(); $table->string('title'); - Relación polimórfica. En Laravel significa que un mismo modelo (por ejemplo Comment) puede relacionarse con varios tipos de modelos diferentes usando una sola relación. Ejemplo:
Un comentario puede estar.
- En un post.
- En un video.
- En una foto.
// Comment.php public function commentable() { return $this->morphTo(); // puede ser Post o Video } // Post.php public function comments() { return $this->morphMany(Comment::class, 'commentable'); } - Relación polimórfica (Muchos a Muchos Polimórfica).
Un Tag puede estar en Posts o en Videos (o cualquier otro modelo).
Uso práctico:// Tag.php class Tag extends Model { public function posts() { return $this->morphedByMany(Post::class, 'taggable'); } public function videos() { return $this->morphedByMany(Video::class, 'taggable'); } } // Post.php class Post extends Model { public function tags() { return $this->morphToMany(Tag::class, 'taggable'); } } // Video.php class Video extends Model { public function tags() { return $this->morphToMany(Tag::class, 'taggable'); } }
// Asignar tags $post = Post::find(1); $post->tags()->sync([1, 3, 5]); // tags con id 1,3,5 $video = Video::find(2); $video->tags()->attach(2); // Obtener tags $tagsDelPost = $post->tags; // Collection $tagsDelVideo = $video->tags; // Desde el tag saber qué modelos tiene $tag = Tag::find(1); $todosLosPosts = $tag->posts; $todosLosVideos = $tag->videos; // Filtrar con eager loading $posts = Post::with('tags')->get();
- "with('posts')" → eager loading (evita N+1 queries).
- "withCount('posts')" → cuenta sin cargar los registros.
- "whereHas('posts')" → filtrar usuarios que tengan posts.
- "has('posts')" → mismo pero más simple
- "doesntHave('posts')" → no tiene registros relacionados, en este caso "posts". Por ejemplo buscar ususarios sin posts.