サイトアイコン IT NEWS

【Laravel】DB登録で必ずuser_idを入れ、検索は自動でuser_idを含ませる方法

laravel-userable

例えば、データベースに登録する際、どのユーザーが登録したかを記録しておきたい場合、もしくは、登録したユーザーのみ閲覧・編集・削除を可能にしたい場合などには、誰がデータを登録したのかログイン中user_idを内容と一緒に保存する必要があります。
しかし、Laravelのマニュアルに従った方法では、毎回登録時にuser_idを挿入する処理を書かなければなりません。
そこで、Laravelモデルに定義されているイベントグローバルスコープaddGlobalScope関数)を使ってこれらを解決していきます。

Traits(トレイト)を作成する

トレイトとは、PHP 5.4.0 以降で導入されたコードを再利用するための仕組みです。
ここに登録と検索の際に使用するコードを書いておきます。

トレイトは、PHP のような単一継承言語でコードを再利用するための仕組みのひとつです。
トレイトは、単一継承の制約を減らすために作られたもので、 いくつかのメソッド群を異なるクラス階層にある独立したクラスで再利用できるようにします。
トレイトとクラスを組み合わせた構文は複雑さを軽減させてくれ、 多重継承や Mixin に関連するありがちな問題を回避することもできます。

PHP: トレイト – Manual

さて、まずはuser_idを登録・検索する処理を作成していきましょう。

App\Userable.php

<?php
namespace App;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;

trait Userable
{
    public static function bootUserable()
    {
        static::addGlobalScope('mine', function(Builder $builder) {
            $builder->where('user_id', auth()->id());
        });
        
        static::creating(function (Model $model) {
            $model->user_id = auth()->id();
        });
    }
}

ココだけを見ると、モデルboot()で書けばいいじゃん?と思ったかもしれませんが、複数のモデルテーブル)にも同じことがしたい場合はトレイトを使った方が便利です。
そして、それぞれのモデルuseして継承します。

ユーザーIDを使用する際の注意点

addGlobalScope関数を利用する際に、かなりハマってしまったのですが、ログイン中にも関わらずauth()NULLになって、正常にデータを取得できませんでした。
原因はProvidersAppServiceProvider.phpView::share()しているモデルでこのトレイトを使おうとしたから。
こんな感じで。

View::share('persons', Person::pluck('name', 'id'));

どうやらプロバイダー内ではログイン情報を持っていないらしい。
ちなみに、Auth::id()でもダメだよ。
悩んだ末、最終的にはミドルウェアView::share()するように修正した。

App\Person.php(通常モデル)

<?php
namespace App;

use Illuminate\Database\Eloquent\Model;
use App\Userable;

class Person extends Model
{
    use Userable;
    
    /**
     * The database table used by the model.
     *
     * @var string
     */
    protected $table = 'persons';

    /**
    * The database primary key value.
    *
    * @var string
    */
    protected $primaryKey = 'id';

    /**
     * Attributes that should be mass-assignable.
     *
     * @var array
     */
    protected $fillable = ['name'];
}

これだけで、insertする場合にはuser_idも自動で登録、selectする場合には検索条件にwhere user_id = [ログイン中のID]を自動で入れてくれます。
また、creating以外にもイベントが用意されているので、updatedeleteをする際にも自動で何らかの処理を挿入することができます。

定義されているイベント一覧

イベント名説明
creating作成するとき
created作成したとき
updating更新するとき
updated更新したとき
saving保存するとき(制作でも、更新でも)
saved保存したとき(制作でも、更新でも)
deleting削除するとき
deleted削除したとき
restoringソフト削除をレストアするとき
restoredソフト削除をレストアしたとき
引用:Eloquentに惚れちゃう便利な機能 – Qiita

皆さんありがとうございます。お世話になっています。

モバイルバージョンを終了