Laravelで、単一テーブル継承(STI)を簡単に実現


単一テーブル継承の理解が間違っていたらごめんなさい。

Laravel 5.2 から、 Global scope という機能が使えるようになった。

これにより、全てのクエリに自動的に条件を追加できるため、クラスの継承を使い、同一のテーブルを性質に分けて実装することが可能。

例えば、Q&Aサイトなどで、投稿(posts) の種類として 記事(article) と 質問(question) に分けられるとする。

poststagsusers と関連があり、その処理は共通化したいため一つのテーブルに収めたい。
articlequestion には固有の処理を持たせたい。

こんな状況だと

class Article extends Post
{
    protected $table = 'posts';

    protected static function boot()
    {
        parent::boot();

        static::addGlobalScope('article', function (Builder $builder) {
            $builder->where('type', 'article');
        });
    }
}

これにより、 where type = 'article' が全ての Article が発するクエリに付加される。

>>> App\Article::where('id', 1)->toSql()
=> "select * from `posts` where `id` = ? and `type` = ?"

実際、Laravelの提供する SoftDeletes トレイトもほぼ同じように実装されている(らしい)。