🏰

Laravel(Eloquent)でのリレーションメモ

2024/06/13に公開

hasMany

「一対多」の関係を示す。一つのモデルが他の多数のモデルに関連している場合に使用される。たとえば、一つのUserが複数のPostを持っている場合

class User extends Model
{
    public function posts()
    {
        return $this->hasMany(Post::class);
    }
}

belongsToMany

「多対多」の関係を示す。二つのモデルが互いに複数の関連を持ち合う場合に使用される。たとえば、複数のUserが複数のRoleに属する場合

class User extends Model
{
    public function roles()
    {
        return $this->belongsToMany(Role::class);
    }
}

class Role extends Model
{
    public function users()
    {
        return $this->belongsToMany(User::class);
    }
}

※上記の場合、中間テーブルが必要

belongsTo

「多対一」の関係を示す。多数のモデルが一つのモデルに所属する場合に使用される。たとえば、例えば、多くのPostが一人のUserに所属している場合

class Post extends Model
{
    public function user()
    {
        return $this->belongsTo(User::class);
    }
}

hasOne

「一対一」の関係を示す。一つのモデルがもう一つのモデルと排他的な関連を持っている場合に使用される。例えば、各Userが一つのProfileを持っている場合

class User extends Model
{
    public function profile()
    {
        return $this->hasOne(Profile::class);
    }
}

morphOne

ポリモーフィック関連の一種で、「一対一」の関係を表すが、褜索対象のモデルが複数の可能性がある場合に使用される。例えば、ImageがUserまたはProductに属する場合

class Image extends Model
{
    public function imageable()
    {
        return $this->morphTo();
    }
}

class User extends Model
{
    public function image()
    {
        return $this->morphOne(Image::class, 'imageable');
    }
}

class Product extends Model
{
    public function image()
    {
        return $this->morphOne(Image::class, 'imageable');
    }
}

morphToMany

ポリモーフィック関連で、「多対多」の関係を表す。たとえばTagがPostやVideoなど複数の種類のモデルに関連付けられる状況を管理できる。

class Tag extends Model
{
    public function posts()
    {
        return $this->morphedByMany(Post::class, 'taggable');
    }

    public function videos()
    {
        return $this->morphedByMany(Video::class, 'taggable');
    }
}

class Post extends Model
{
    public function tags()
    {
        return $this->morphToMany(Tag::class, 'taggable');
    }
}

class Video extends Model
{
    public function tags()
    {
    return $this->morphToMany(Tag::class, 'taggable');
    }
}

morphedByMany

morphedByManyリレーションはmorphToManyと対になる関係で、特に多対多のポリモーフィック関係で使用される。morphedByManyは、関連付けられたモデルの側で定義され、morphToManyが関連付ける側のモデルで定義される。複数の異なるタイプのモデルが一つの共通のモデル(例えばTag)に関連付けられる場合に使用される。

class Tag extends Model
{
    public function posts()
    {
        return $this->morphedByMany(Post::class, 'taggable');
    }

    public function videos()
    {
        return $this->morphedByMany(Video::class, 'taggable');
    }
}
class Post extends Model
{
    public function tags()
    {
        return $this->morphToMany(Tag::class, 'taggable');
    }
}

class Video extends ...

morphTo

ポリモーフィック関連での「一対一」または「多対一」の関係を表す。morphToは通常、ターゲットとなるモデルが実行時にしか特定されない場合に使用される。たとえば、異なる種類のコメント可能なモデル(ポスト、ビデオなど)に対するコメントを管理する場合

class Comment extends Model
{
    public function commentable()
    {
        return $this->morphTo();
    }
}

感想

ポリモーフィック関係が難しい。既存コードのModelを見てすぐにリレーションを頭の中で構築できるように慣らしていきたい。

参考記事

https://laravel.com/api/11.x/Illuminate/Database/Eloquent/Relations.html

https://qiita.com/ramuneru/items/db43589551dd0c00fef9

https://qiita.com/sgrs38/items/af0a5082f666f268e4cc

Discussion