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;
en

$user->posts

Tipos principales de relaciones en Eloquent

Tipo Método en el modelo Descripción Ejemplo típico
One to One hasOne / belongsTo Un registro tiene exactamente uno de otro Usuario → Perfil
One to Many hasMany / belongsTo Un registro tiene muchos de otro Usuario → Posts
Many to Many belongsToMany Muchos registros de A con muchos de B Usuario ↔ Roles
Has Many Through hasManyThrough Acceder a una relación a través de una intermedia País → Posts (a través de Usuarios)
Polymorphic morphOne / morphMany Una relación que puede ser de varios tipos Comentarios en Posts o Videos
Polymorphic Many morphToMany / morphedByMany Many-to-many polimórfica Tags en Posts o Videos

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).

    // 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');
        }
    }
    
    Uso práctico:

    // 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();
    
Métodos útiles que vienen con las relaciones
  • "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.