章: 第2章: データベース応用
->where('status', 'published') を何度も書いていませんか?
コントローラAでも、サービスクラスBでも、同じ ->where('status', 'published') を繰り返し書いていませんか?もし「公開済み」の定義が変わったら、すべての箇所を変更しなければなりません。
スコープはこうした繰り返す条件をモデルに閉じ込め、Post::published() と書くだけで条件を再利用できます。キャストはDBから取得した値の型変換を自動化し、コントローラで手動変換する必要をなくします。
スコープとキャストの実装
<?php
class Post extends Model {
public function scopePublished(Builder $query): Builder {
return $query->where('status', 'published');
}
protected $casts = [
'meta' => 'array',
'published_at' => 'datetime',
];
}
$posts = Post::published()->get();
コントローラに書く vs モデルのスコープ
| 観点 | コントローラに直書き | モデルのスコープ |
| 再利用性 | 各コントローラに同じコード | Post::published() だけで使える |
| 条件変更 | 全箇所を修正 | モデルだけ修正 |
| テスト | コントローラごとにテスト | スコープを単独でテスト |
| 読みやすさ | クエリの意図が埋もれる | メソッド名が意図を表す |
チェックポイント: スコープのメソッド名は
scopeプレフィックスを付けて定義しますが、呼び出し時はPost::published()と省略形で使います。
キャストの種類
<?php
class Post extends Model {
protected $casts = [
'meta' => 'array', // JSON文字列→配列
'published_at' => 'datetime', // 文字列→Carbonインスタンス
'is_featured' => 'boolean', // "0"/"1"→true/false
'price' => 'decimal:2', // 文字列→小数点2桁
];
}
$post = Post::find(1);
$post->meta['key']; // 配列として直接アクセス
$post->published_at->format('Y/m/d'); // Carbonのメソッドが使える
$post->is_featured === true; // boolean比較が正確
チェックポイント:
'datetime'キャストを使うと、$post->published_atが自動的にCarbonインスタンスになります。日付操作のコードが大幅にシンプルになります。
まとめ & 次のステップ
- スコープはクエリの繰り返し条件をモデルに集めて再利用できる
- キャストはDBから取得した値の型変換を自動化し、手動変換コードをなくす
- どちらもコントローラを薄く保ち、モデルに責務を集中させる設計
次回はSeederとテストデータ管理を学びます。開発・テスト環境に一貫したデータを自動投入する仕組みです。