てくてくテック

【Laravel】モデルでイベントごとに処理をさせる方法

どーも!たかぽんです!

今回はLaravelのモデルにて使えるとっても便利な"イベント"について色々試してみようと思います。

では早速みていきましょう!

Laravelのモデルのイベントって?

この機能、ついこないだまで僕知らなかったんですが...

モデルではイベントを扱うことができます...!

以下リンク先の結構下の方に"イベント"という項目があるはずです。

このイベントとは、例えばモデルをcreate, save, delete, update等、操作することを指しています。

これらのイベントを実行する際、合わせてなんらかの処理を行わせたい場合にとっても便利なんですね。

例えば...

あるテーブルにモデルのデータを新規作成(createやsave)する際にはcreateddayを現在の日付で作成したい。

とか、あるテーブルのデータを更新(update)する際にはupdateddayを現在の日付で更新するようにしたい。

といったイメージです。(上記はデフォルトでついてた気がするけど)

僕の場合は認証用のランダムトークンを持つテーブルに新しくデータを作成する場合は常にTokenカラムにランダムな文字列を付与してあげるといったことをしたかったんです。

上記の処理は別に今回説明するモデルのイベントを使わずとも実装可能です。

ただ、仮にcreateする際は常にしたい処理がある場合、普通の書き方だとcreateをする前にその処理を行い、モデルのカラムと同じ名前のプロパティにその値を入れてあげて、createをすると思います。

別のコントローラー等で呼び出されて、同じテーブルに対してcreateする場合も全く同じ処理を書く必要があります。

ただ、そのモデル自体に対してcreateが行われる場合にのみ行う処理が定義できたら、上記のような重複がなくなるわけです。

つまり、DRYになるわけですね。

言葉だけだと難しいので、コードをみていきましょう!

モデルのイベントを触ってみる!

では、早速ですが、簡単な例を用いて解説していきますね。

laravelの新規作成時のデフォルトUserモデルを使っていきます。

<?php

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

    // ここを追加!
    public static function boot()
	  {
		  parent::boot();

		  self::creating(function (User $user) {
			  $user->remember_token = 'createされるとこの文字列が入ります';
		  });
	  }
}

このモデルに"bootメソッド"を追加します。

一番下にここを追加!としていますが、そこですね。

ここで、self::creatingや、self::save等、イベント発生時にすることを指定してあげれば、そのイベントが発生した場合に自動で処理を行ってくれるようになります。

これだけなんです!

今回追加しているのは、creatingで、このモデルに対してcreateされたら、その際に渡すモデルを受け取り、そのモデルの"remember_token"に対して文字を入れるように指定しています。

テストなので、わかりやすいように定型文を入れていますが、本来ならStr::random(64)的な感じでランダムな文字列等が入るイメージですね。

こうすることで、どこでこのモデルを用いてcreateされても、remember_tokenには必ずこの文字列が入ることになります。

例えば試しにコントローラー側で以下ようにcreateしてあげると・・・?

User::create(['name' => 'create', 'email' => 'create@create', 'password' => 'create']);

以下のように、本来はname, email, passwordだけ入れてcreateしたはずが、ちゃんとremember_tokenに値が入っているのが確認できました!

ちなみに、created_atとupdated_atはデフォルトで入るようになっている(laravel側でそうなってます)ので、はいっています。

takapon-test=> select * from users;
 id |    name    |     email      | email_verified_at |  password  |           remember_token           |     created_at      |     updated_at
----+------------+----------------+-------------------+------------+------------------------------------+---------------------+---------------------
  9 | create     | create@create  |                   | create     | createされるとこの文字列が入ります      | 2020-04-25 12:32:50 | 2020-04-25 12:32:50

もちろん、別のコントローラーから呼び出したとしてもちゃんとremember_tokenに入るようになっています。

実は、今回実装した方法は公式の方法とは違います。

先ほど貼り付けていたリンク先のやつではサービスプロバイダー登録したりー・・・と色々やっているんですが...

比較的楽にできる方法を紹介しました。

比較的楽に実装できるのにとっても便利です...

まとめ

さて、こんかいはモデルのイベント発生時に処理を組み込む方法を解説しました。

正直初めて知った瞬間、え、こんなこともできるの?w

と思わず思ってしまいましたね...

これからまたモデル周りを回収する時のアイデアが一つ増えました。

是非みなさんも何か使えるユースケースがあれば活用してみてください。

それでわ!

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