Laravelのモデルイベント(creating, updating)を使う方法
生徒
「Laravelでデータを保存するときに、自動で値を設定したりチェックしたりする方法ってありますか?」
先生
「はい、それにはEloquentのモデルイベントを使うと便利です。例えばcreatingやupdatingといったイベントがあります。」
生徒
「モデルイベントって何ですか?」
先生
「モデルイベントとは、モデルがデータベースに保存される前後など、特定のタイミングで自動的に処理を行う仕組みです。データが作られる前に値を加工したり、更新される前にチェックしたりできます。」
生徒
「なるほど、具体的にはどうやって使うんですか?」
先生
「では、基本的な使い方を順に見ていきましょう。」
1. creatingイベントで「新規保存前」に自動処理を追加する
Laravelでデータを新しく保存する際、「保存ボタンが押された瞬間に、自動で特定の値をセットしたい」という場面がよくあります。これを実現するのがcreatingイベントです。
例えば、プログラミング初心者の方でもイメージしやすい「会員登録システム」を考えてみましょう。ユーザー一人ひとりに、重複しない特別なID(UUID)を自動で割り振る仕組みを、モデルイベントを使って実装します。
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
class User extends Model
{
/**
* モデルの起動時に呼ばれるメソッド
*/
protected static function booted()
{
// 1. データを新しく作ろうとしている(creating)タイミングをキャッチ
static::creating(function ($user) {
// 2. 保存される直前に、uuidという項目に自動でランダムな値を代入
$user->uuid = (string) Str::uuid();
// ログを出して動きを確認(デバッグ用)
\Log::info('新しいユーザーのUUIDを自動設定しました:' . $user->uuid);
});
}
}
このコードのポイントは、bootedという「モデルが準備されたときに動くメソッド」の中に処理を書くことです。
なぜこれが便利なの?
もしこれを使わないと、ユーザーを登録する全ての場所(コントローラなど)で毎回UUIDを生成するコードを書かなければなりません。モデルイベントを使えば、「ユーザーが作られるときはいつでも、自動的にこのルールを適用する」という設定が一箇所で済むため、書き忘れやミスを未然に防ぐことができます。
実行時のイメージ:
1. ユーザーが名前を入力して登録ボタンを押す
2. Laravelが「creatingイベント」を検知
3. 自動で UUID (例: 550e8400-e29b-41d4-a716-446655440000) が生成され、データにセットされる
4. データベースに保存完了!
2. updatingイベントで「更新の直前」に自動処理を実行する
LaravelのEloquentモデルには、データベースのデータが書き換わる瞬間に特定の処理を割り込ませる「イベント」という便利な機能があります。その中でもupdatingイベントは、実際の更新処理が完了する直前に実行されるため、値の自動補完やログの記録に最適です。
プログラミング未経験の方でも分かりやすい例として、「誰がこのデータを編集したか」を自動で記録するサンプルを見てみましょう。これを設定しておけば、プログラムのあちこちで「更新者ID」を書き込むコードを何度も書く必要がなくなります。
protected static function booted()
{
// データの更新(保存)が実行される直前のタイミングで呼び出される
static::updating(function ($user) {
// 現在ログインしているユーザーのIDを「updated_by」カラムに自動代入
// これにより「いつ、誰が」変更したかの証跡を確実に残せます
if (auth()->check()) {
$user->updated_by = auth()->id();
}
});
}
このコードのポイントは、モデルのbootedメソッド内でstatic::updatingを定義している点です。これにより、システム内のどこかでユーザー情報が保存(save)されるたびに、Laravelが裏側で自動的にログインユーザーのIDをセットしてくれます。
例えば、管理画面で名前を変更して保存ボタンを押した際、内部では以下のような流れで処理が進みます。
1. 編集画面から新しい名前が送信される
2. Laravelが「updating」イベントを検知し、コードを実行
3. updated_by に「操作した人のID」を自動セット(← ここが今回のポイント!)
4. データベースの情報を最終的に書き換え(更新完了)
このように、手動で毎回カラムを指定しなくても「更新者の足跡」を自動で残せるようになるため、大規模なシステム開発やチームでの開発では必須級のテクニックと言えます。初心者の方は、まずは「保存される前に自動で何かの値を埋めるためのフック(引っ掛け)」として覚えておくと非常に役立ちます。
3. モデルイベント(Model Events)を使うメリット
Laravelの「モデルイベント」を活用する最大のメリットは、「特定のデータ操作に関連する処理を1箇所に集約できる」という点です。通常、データの保存や更新時に行いたい処理をコントローラに記述すると、同じようなコードが散らばり、修正漏れやミスの原因になります。
モデルイベントを使えば、以下のようなメリットを享受できます。
- コードの共通化: コントローラやサービスクラスに同じ処理を何度も書く必要がなくなり、コードが驚くほどスッキリします。
- データの一貫性: どこからデータを保存しても必ず同じ処理(例:ステータスの自動更新など)が実行されるため、データベースの整合性が保たれます。
- ミスの削減: 「UUIDの発行忘れ」や「作成者の記録漏れ」といった人為的なミスを構造的に防ぐことができます。
【初心者向け】具体的な活用シーンとサンプル
例えば、プログラミング初心者の方がイメージしやすい例として、「ユーザーを新しく登録したときに、自動的にユニークなID(UUID)を割り振る」という処理を考えてみましょう。
もしモデルイベントを使わない場合、ユーザーを作るたびに毎回IDを生成するコードを書かなければなりませんが、モデルイベントを使えば、「ユーザーが作成される直前(creating)」に自動で処理を挟み込むことができます。
// モデルの中で「作成される直前」の動きを定義するイメージ
protected static function booted()
{
static::creating(function ($user) {
// ユーザーがデータベースに保存される前に、自動でUUIDをセットする
$user->uuid = (string) \Str::uuid();
echo "自動的にUUIDを生成しました!";
});
}
この設定をしておくだけで、コントローラ側で意識しなくても、データ保存時に以下のような結果が得られます。
(実行結果のイメージ)
名前: 田中太郎
メール: tanaka@example.com
生成されたUUID: 550e8400-e29b-41d4-a716-446655440000(自動付与)
このように、「誰が操作しても必ず実行したいルール」をシステム側に任せられるのが、モデルイベントの強力な強みです。保守性の高いアプリケーションを目指すなら、避けては通れない便利な機能と言えるでしょう。
4. 注意点とポイント:初心者がハマりやすい落とし穴
Laravelのモデルイベントは非常に強力ですが、正しく理解していないと予期せぬ不具合の原因になります。ここでは、プログラミング未経験の方でも失敗しないための重要なポイントを整理しました。
① 処理の重複に注意!
モデルイベントは「モデルが操作された瞬間に自動で」実行されます。そのため、以前のようにコントローラ(Controller)側に同じ処理を書いてしまうと、二重で処理が走ってしまいます。「共通のデータ加工はモデルイベントに任せ、コントローラはスッキリさせる」のが現代的なSEOにも強い、保守性の高いコードの書き方です。
② 「保存前」と「保存後」の違いを意識する
今回紹介したcreatingやupdatingは、データがデータベースに書き込まれる直前に動くイベントです。一方で、保存された直後に動くcreatedやupdatedというイベントも存在します。
- 保存前(creatingなど): データの書き換えやバリデーションに向いています。
- 保存後(createdなど): 会員登録完了メールの送信や、ログの記録などに向いています。
③ 初心者向けの具体例:全角を半角に自動変換
例えば、ユーザーが入力した「電話番号」や「郵便番号」を、保存する前に自動で半角に変換する処理を考えてみましょう。これなら、どこからデータを保存しても常にきれいな形式でデータベースに保存されます。
// モデルの中で、保存前に全角英数字を半角に変換する例
protected static function booted()
{
static::creating(function ($user) {
// mb_convert_kanaを使って、全角を半角(as)に変換
$user->tel = mb_convert_kana($user->tel, "as");
});
}
このように、モデルイベントを使いこなすと、入力漏れやミスを防ぎ、アプリケーション全体の信頼性をグッと高めることができます。まずは「保存前の自動処理」から少しずつ試してみましょう。
まとめ
今回はLaravel(ララベル)の強力な機能の一つである「モデルイベント(Eloquentイベント)」、特にデータの保存や更新のタイミングで威力を発揮する「creating」と「updating」について詳しく解説してきました。Webアプリケーションを開発していると、データベースに値を保存する直前に「特定のIDを自動付与したい」「特定のカラムを自動計算して埋めたい」といった場面が多々あります。これらをコントローラに都度書いていると、コードが煩雑になり、共通化も難しくなります。しかし、モデルイベントを活用すれば、モデル自身の責務としてこれらをスマートに一括管理できるのです。
モデルイベントを活用する実践的なメリット
Eloquentモデルイベントを利用することで、開発効率は劇的に向上します。主なメリットを整理してみましょう。
- DRY(Don't Repeat Yourself)原則の維持: 同じ処理を複数のコントローラに書く必要がなくなります。
- データの一貫性の担保: どこからデータを保存しても必ずイベントが実行されるため、値の漏れを防げます。
- コードの可読性向上: ビジネスロジックがモデルに集約され、コントローラがスッキリします。
creatingとupdatingの具体的な使い分け
改めて、今回紹介した二つのイベントの違いを復習しておきましょう。
creating: 新規レコードが作成(insert)される直前にフックされます。IDの自動生成や初期ステータスの設定に向いています。
updating: 既存のレコードが変更(update)される直前にフックされます。変更履歴の記録や、更新者のID保存に最適です。
応用:複数のイベントを組み合わせたサンプルコード
実践では、一つのモデルに対して複数のイベントを定義することが一般的です。以下のサンプルプログラムでは、新規作成時には管理用コードを生成し、更新時には最終更新ユーザーを記録する、より現場に近い形の実装を紹介します。
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Auth;
class Product extends Model
{
/**
* モデルの「初期起動」メソッド
*/
protected static function booted()
{
// 新規作成時のみ実行される処理
static::creating(function ($product) {
// 商品コードをランダムな文字列で自動生成
if (empty($product->product_code)) {
$product->product_code = 'PRD-' . strtoupper(Str::random(8));
}
// ログ出力用などの初期設定
logger('新しい商品が作成されます。');
});
// 更新時のみ実行される処理
static::updating(function ($product) {
// ログイン中であれば、更新者IDを自動保存
if (Auth::check()) {
$product->last_updated_by = Auth::id();
}
logger('商品ID:' . $product->id . ' が更新されます。');
});
}
}
このようにbootedメソッド内でstatic::creatingやstatic::updatingを呼び出すだけで、Laravelが裏側ですべて面倒を見てくれます。非常に強力ですね。
モデルオブザーバー(Observers)という選択肢
もし、モデル内に書くイベント処理が肥大化してしまった場合は、「Observer(オブザーバー)」クラスを作成して処理を切り出す方法もあります。これにより、モデルクラス自体を軽量に保つことができます。
php artisan make:observer UserObserver --model=User
このコマンドを実行すると、イベント専用のクラスが生成されます。小規模なうちはモデル内のbootedで十分ですが、大規模な開発ではObserverの利用も検討してみてください。
最後に
Laravelのモデルイベントは、PHPでのWeb制作を一段上のレベルに引き上げてくれる素晴らしい仕組みです。特にCRUD操作(作成、読み取り、更新、削除)が中心となるシステムでは、この自動化の仕組みを知っているかどうかで、コードの品質に大きな差が出ます。まずは、今回紹介したコードを実際に自分のプロジェクトに組み込んで、データベースに反映される動きを確認してみてください。きっとその便利さに驚くはずです。
生徒
「先生、まとめまで読んで、モデルイベントの使いどころがかなり具体的にイメージできました!特にcreatingでUUIDを生成するのって、めちゃくちゃ実用的ですね。」
先生
「そう言ってもらえると嬉しいです。UUID以外にも、例えばブログ記事の『スラッグ(URLの一部)』をタイトルから自動生成して保存するといった使い方もよくされますよ。」
生徒
「あ、それ便利そう!でも、もしイベントの中でエラーが起きたらどうなるんですか?データベースの保存は止まってしまうんでしょうか?」
先生
「いい質問ですね。例えばcreatingイベントの中でfalseを返すと、実は保存処理自体がキャンセルされます。これを利用して、特定の条件を満たさない場合に保存をブロックする、といった簡易的なバリデーションのような使い方もできるんですよ。」
生徒
「へぇー!単に値を埋めるだけじゃなくて、守り神みたいな役割もできるんですね。ちなみに、これってsave()メソッドを呼んだときに勝手に動くんですか?」
先生
「その通りです。save()だけでなく、create()やupdate()といったEloqunetのメソッドを介せば自動的に発火します。ただし、DB::table('users')->update(...)のように、クエリビルダを直接使って更新した場合にはイベントが飛ばないという注意点があります。ここは初心者がハマりやすいポイントですね。」
生徒
「なるほど、Eloquentを通すのが大前提なんですね。使い分けを意識します!あと、更新者のIDを保存するupdatingの例もありましたが、これってログインしていないユーザーが操作したときはどうすればいいですか?」
先生
「その場合は、Auth::check()でチェックを入れて、ログインしている場合のみ値をセットするように条件分岐を書くのが一般的ですね。先ほどのサンプルコードにもその処理を入れましたが、エラーを防ぐための基本的な工夫です。」
生徒
「分かりました!モデルイベントを使いこなして、スマートなLaravelエンジニアを目指します!次は削除したときのdeletingイベントとかも調べてみたいです。」
先生
「いい意気込みですね!削除時に紐づく子データを一緒に消すといった処理もdeletingでよく書かれます。ぜひステップアップして挑戦してみてくださいね。」