DIVX テックブログ

catch-img

MySQLトリガーとLaravelオブザーバーの違い


目次[非表示]

  1. 1.はじめに
  2. 2.Laravelのオブザーバーとは何か?
      1. 2.0.1.使い方(登録方法)
  3. 3.MySQLのトリガーとは何か?
      1. 3.0.1.使い方(登録方法)
  4. 4.両者の比較
      1. 4.0.1.Laravelオブザーバー
      2. 4.0.2.MySQLトリガー
  5. 5.LaravelオブザーバーとMySQLトリガー、どちらを選択すべき?
  6. 6.まとめ
  7. 7.お悩みご相談ください

はじめに

データベースのテーブルにデータを追加した後に決められた処理を実施したい場合があると思います。
現在担当している案件では、LaravelとMySQLを使用しており、それぞれで上記のようなデータの操作に伴って決められた処理を実行できる仕組みがあることがわかりました。


そのためLaravelのオブザーバー機能とMySQLのトリガー機能について、それぞれの概要や実装方法、メリット・デメリットを調査しました。

Laravelのオブザーバーとは何か?

Laravelのオブザーバーは、Eloquentモデルにおける操作イベント(作成、更新、削除など)をキャッチして、関連するビジネスロジックを自動的に実行するクラスです。


オブザーバーはアプリケーションレベルで動作するので、Laravelの他の機能や依存関係の注入が簡単に行えます。

使い方(登録方法)


バージョン情報は以下のとおりです。

PHP 8.3
Laravel 11

オブザーバーを使う場合は、モデルごとにオブザーバーを用意し、サービスプロバイダに登録する必要があります。


以下のコマンドを実行することでApp/ObserversディレクトリにUserObserver.phpというファイルが作成されます。
(例としてUserモデルを使用することを想定します)

php artisan make:observer UserObserver --model=User

作成されたファイルを確認すると以下のようになっています。

<?php

namespace App\Observers;

use App\Models\User;

class UserObserver
{
/**

 * ユーザーの"created"イベントの処理
 */
public function created(User $user): void
{
    // ...
}

/**
 * ユーザーの"updated"イベントの処理
 */
public function updated(User $user): void
{
    // ...
}

/**
 * ユーザーの"deleted"イベントの処理
 */
public function deleted(User $user): void
{
    // ...
}

/**
 * ユーザーの"restored"イベントの処理
 */
public function restored(User $user): void
{
    // ...
}

/**
 * ユーザーの"forceDeleted"イベントの処理
 */
public function forceDeleted(User $user): void
{
    // ...
}
}

--model=User で指定したモデル名をもとに、Modelsディレクトリから参照していたりメソッドの引数に設定されていることがわかります。


オブザーバー内で使用できるメソッドはLaravelのイベント処理でフックしている処理を指定することができます。
https://readouble.com/laravel/11.x/ja/eloquent.html#events


例えばUserテーブルへ挿入される前に処理を行いたい場合は以下のメソッドを用意することで実現できます。

public function creating(User $user)
{
 //...
}

上記で用意したオブザーバーをモデルに関連づけるため、対応するモデルにObservedByアトリビュートを指定します。こうすることでEloquentイベントのオブザーバー機能を利用できます。

use App\Observers\UserObserver;
use Illuminate\Database\Eloquent\Attributes\ObservedBy;

#[ObservedBy([UserObserver::class])]
class User extends Authenticatable
{
  //...
}

上記の設定はLaravelのバージョンが11のものになります。バージョンによって設定方法が異なりますので適宜公式ドキュメントを参考に設定しましょう。
https://laravel.com/docs/11.x/eloquent#observers


以上の設定を行うことで、例えば以下のような処理を行うとユーザーデータが作成された後にオブザーバーが動作しログが出力されるようになります。

//ユーザーを作成
$user = User::create([
  'name' => 'Test User',
  'email' => 'test@example.com'
]);


<?php
  namespace App\Observers;
  use App\Models\User;
  class UserObserver
  {
    public function created(User $user): void
    {
      Log::info('User created: ' . $user->id);
    }
  }

MySQLのトリガーとは何か?

MySQLのトリガーは、テーブルに対する操作が行われるときに自動的に実行されるストアドオブジェクトです。
トリガーはデータベースレベルで動作するためアプリケーションに依存せず、データの整合性を高いパフォーマンスで維持することができます。

使い方(登録方法)

バージョン情報は以下のとおりです。

MySQL 8.0

MySQLトリガーは、データベースに対して以下のようなSQL文を実行することで登録することができます。
例えば以下の処理では、Userテーブルにユーザーを追加したときに、作成したユーザーIDをUserHistoryテーブルに挿入するといった単純な履歴機能を提供することができます。

DELIMITER //

CREATE TRIGGER after_insert_users
AFTER INSERT ON users
FOR EACH ROW
BEGIN
// ここに行いたい処理を記述する
// user_historyテーブルのレコード情報の設定は割愛します
INSERT INTO user_history (user_id) VALUES (NEW.id);
END; //

DELIMITER ;

MySQLクライアントによってはDELIMITERが不要になる場合がありますが、一般的にはストアドプロシージャやトリガーを作成する際にはDELIMITERを使用することが推奨されます。ご利用の環境によって適宜設定を行なってください。


なお、作成したトリガーは以下のコマンドで確認することができます。

show triggers;

以上の設定を行うことで、アプリケーション側の処理によらず、データベースが行う操作をトリガーに処理が実行されるようになります。

両者の比較

LaravelオブザーバーとMySQLトリガーは、それぞれ異なる視点とレイヤーで動作するため、どちらが適しているかは具体的な要件や環境に依存します。以下では、両者の具体的な違いや特徴を比較します。

Laravelオブザーバー

  • メリット
    • コードベースで管理しやすい
      • オブザーバーはオブザーバーの設定も含めアプリケーションのコードに含まれるため、コード管理システムでバージョン管理をすることができます。適切にコードを管理することによりMySQLトリガーと比べて案件の引き継ぎ漏れや設定のし忘れが発生しにくいです。
    • コードの再利用性
      • オブザーバーで定義された処理は再利用できます。複数のモデルで同じイベントに対する共通の処理が必要な場合は共通のオブザーバーを定義することでそれを再利用できます。
  • デメリット
    • パフォーマンスの影響
      • オブザーバーはアプリケーションレベルで動作するため、イベントが多く発生する場合や、オブザーバー内の処理が重い場合にはパフォーマンスに影響を与える可能性があります。
    • すべての処理に使えるわけではない
      • Eloquentのバルク操作(updateメソッドなど)では、saving、saved、updating、updatedイベントが発火しないため、特定のシチュエーションではイベントがトリガーされず、注意が必要です。(https://laravel.com/docs/11.x/eloquent#mass-updates)

MySQLトリガー

  • メリット
    • データの一貫性
      • トリガーはデータベースレベルで動作するため、アプリケーション層を介さずにデータの整合性を保証します。これにより、異なるアプリケーションからのデータ操作でも一貫性を保つことができます。
    • 自動化の容易さ
      • トリガーを使用することで、特定の操作に対するアクション(例:ログの記録、関連テーブルの更新など)を自動化でき、手動での更新やエラーが発生しやすい処理を減少させることができます。
  • デメリット
    • デバッグが難しい
      • トリガーはデータベース内で動作するため、データベースの処理でエラーが発生した際のデバッグが難しいです。SQLベースでのトリガーの管理や解析が必要となります。
    • 移行時の管理が煩雑
      • トリガーはデータベース内の定義になるため、データベースの移行の際や検証環境など新たに環境を準備する際にトリガーを設定する必要があり管理が煩雑になってしまいます。トリガーを設定するSQLスクリプトを適切に管理することが重要になります。

LaravelオブザーバーとMySQLトリガー、どちらを選択すべき?

個人的にはオブザーバーを選択します。
理由としては、何かしらのロジックなのであればすべてアプリケーションで処理を管理したいからです。バージョン管理ツールでコードを管理することもできますし、デバッグ機能のブレイクポイントの使用もできるため保守管理が楽になるからです。
一方トリガーは環境ごとにトリガーを設定する必要があるため、設定のし忘れが発生するリスクがあります。

まとめ

LaravelオブザーバーとMySQLトリガーの特徴を比較しました。
それぞれに独自のメリットと制約があり、どちらを選ぶかは、アプリケーションの要件や開発体制、運用環境に応じて適切な選択をすることが重要だと思います。
両者の特徴の理解および開発の一助となれば幸いです。

お悩みご相談ください

  ご相談フォーム | 株式会社divx(ディブエックス) DIVXのご相談フォームページです。 株式会社divx(ディブエックス)


お気軽にご相談ください


ご不明な点はお気軽に
お問い合わせください

サービス資料や
お役立ち資料はこちら

DIVXブログ

テックブログ タグ一覧

採用ブログ タグ一覧

人気記事ランキング

GoTopイメージ