👍

Observerを使用してモデルのイベントをキャッチしよう(Laravel)

2021/03/12に公開

今回はLaravelのObserverという機能を紹介します。

Observerを使用することで、モデルのcreate, update, delete,restore,forceDeleteの直後に何かしら処理を施すことができます。

本記事はLaravel8系で試しています。

Observerの作成方法

コマンドでObserverのファイルを作成することができます。

php artisan make:observer UserObserver --model=User

すると、 /app/Observers/UserObserver.php が作成されました。

中身はこのような感じです。

<?php

namespace App\Observers;

use App\Models\User;

class UserObserver
{
    /**
     * Handle the User "created" event.
     *
     * @param  \App\Models\User  $user
     * @return void
     */
    public function created(User $user)
    {
        //
    }

    /**
     * Handle the User "updated" event.
     *
     * @param  \App\Models\User  $user
     * @return void
     */
    public function updated(User $user)
    {
        //
    }

    /**
     * Handle the User "deleted" event.
     *
     * @param  \App\Models\User  $user
     * @return void
     */
    public function deleted(User $user)
    {
        //
    }

    /**
     * Handle the User "restored" event.
     *
     * @param  \App\Models\User  $user
     * @return void
     */
    public function restored(User $user)
    {
        //
    }

    /**
     * Handle the User "force deleted" event.
     *
     * @param  \App\Models\User  $user
     * @return void
     */
    public function forceDeleted(User $user)
    {
        //
    }
}

ユーザーが作成された際に処理を施したい場合は created の中に処理を書いていき、同じように、updateやrestore, delete, forceDeleteにも処理を書くことができます。

restore, forceDeleteとは

create, update, deleteは馴染みのある単語ですが、restore, forceDeleteとは何でしょうか。

これらはモデルで論理削除(softDelete)を使用している際に出てくる言葉です。

論理削除を行う場合、 データベースのレコードを本当に削除するのではなくて、 deleted_at に日付をいれることで、そのレコードはデータベースには残っているけどシステム上削除されたという扱いにしています。

restoreは一度論理削除したけど元に戻す場合、forceDeleteは論理削除ではなく本当にデータベースから削除したい場合に用います。

Observerを使用してユーザーが作成された場合にメール送信を送る

Notificationは作成している前提でいきます(今回の趣旨とは外れるため)

ユーザー登録時にメールを送信したい場合、createdの中にメール送信処理を書いていきます。これだけです!

<?php

namespace App\Observers;

use App\Models\User;

class UserObserver
{
    /**
     * Handle the User "created" event.
     *
     * @param  \App\Models\User  $user
     * @return void
     */
    public function created(User $user)
    {
        $user->sendHogeNotification(); // ← 追記
    }

    /**
     * Handle the User "updated" event.
     *
     * @param  \App\Models\User  $user
     * @return void
     */
    public function updated(User $user)
    {
        //
    }

    /**
     * Handle the User "deleted" event.
     *
     * @param  \App\Models\User  $user
     * @return void
     */
    public function deleted(User $user)
    {
        //
    }

    /**
     * Handle the User "restored" event.
     *
     * @param  \App\Models\User  $user
     * @return void
     */
    public function restored(User $user)
    {
        //
    }

    /**
     * Handle the User "force deleted" event.
     *
     * @param  \App\Models\User  $user
     * @return void
     */
    public function forceDeleted(User $user)
    {
        //
    }
}

Observerを登録して使用できるようにする

上記で作成したObserverを使用するためには、 app/Providers/AppServiceProvider.php にこのように追記してください

<?php

namespace App\Providers;

use App\Models\User;
use App\Observers\UserObserver;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Schema;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        User::observe(UserObserver::class);
    }
}

これでObserverが正常に機能するようになります!

Observerを使うと何が良いのか

Observerを使わなくても普通にユーザー登録時に、処理を書けばいいじゃあああんと思いますよね。

正直、それでも良いです。

しかし、よりよいコードにするためにはControllerに各処理をできるだけ減らした方がいいです。
Controllerに書いた処理はほとんど再利用できないものになってしまうためです。

今回の例でいうと、UserContollerのregisterメソッド意外の別の部分でユーザー登録をする処理を書かないといけなくなった場合に、 $user->sendHogeNotification(); をコピペする必要がありますよね。

しかし、Observerを使用すれば、どのControllerでユーザー登録をしようと必ず $user->sendHogeNotification(); は実行されます。異なるControllerで同じコードを書くよりもこちらの方がクリーンなコードです。

Observerのデメリット

完璧に良いコードを目指すことは必ずしも善とは言えません。
チーム内に技術についていけない人がいる可能性があります。

registerメソッドでユーザー登録をしているはずでそこでメールを送信しているはずなのに、、、registerメソッドにメール送信処理が記述されていない!!なぜなんだあああーー!!と悩む人は出てくると思います。

そのデメリットも踏まえて、Observerを採用するかどうかを検討した方が良いでしょう。

終わりに

今回はObserverを解説しました。

非常に良い機能なのですが、Observerを知らないとコードが追えないことが多々あるので、必ずしも「良いコード is the best」と言い切れないところが悔しいです。

個人開発や全員が技術レベルの高いチームではぜひ使ってみてくださいね!

ではまた!

Discussion