概要
LaravelのValidation(バリデーション/入力値検証)には、入力データのチェック(検証)を行うための便利なルールがあらかじめ用意されています。
そのなかの一つであるunique
ルールの、ちょっと便利な使い方を紹介します。
環境
- PHP 7.3
- Laravel 5.6
実現したいこと
仮に、システムで実現したいことが以下のように定義されているとします。
- あるシステムでユーザーを更新する際、ユーザーのメールアドレスが他のユーザーと重複せずユニークであるかチェックしたい。
- ただし、ユーザーはデータベース上論理削除対象となっているため、論理削除済ユーザーのメールアドレスはチェックの対象外としたい。
- 当然ながら、更新しようとするユーザー自身のメールアドレスもユニークチェックの対象外としなければならない。
- 対象外にしないと、メールアドレスを変更せずにユーザーを更新することができないため。
コード例
FormRequest
を継承したリクエストクラスにValidationルールを定義し、やりたいことを実現する例です。
まず、検証対象のUser
モデルには、論理削除モデルを表すSoftDeletes
トレイトが指定されています。
// namespace, use は省略 /** * App\Models\User * * @property int $id * @property string $name * @property string email * ... */ class User extends Model { use SoftDeletes; $fillable = [ 'name', 'email', ... ]; }
User
の更新リクエストに対応するFormRequest
クラスには、rules()
メソッドに検証ルールを表す配列を定義し、戻り値で返却します。
リクエストデータに、更新対象ユーザーのid
とemail
が含まれているという前提です。
// namespace, use は省略 class UserRequest extends FormRequest { /** * Get the validation rules that apply to the request. * * @return array */ public function rules() { $id = $this->get('id'); return [ 'email' => "unique:users,email,${id},id,deleted_at,NULL", // 以下略... ]; } }
"unique:users,〜"
の箇所がわかりにくいと思います。分解するとこうなります。
unique
:ユニークチェックusers
:対象テーブル名email
:チェックする列名${id}
:除外する値。次の「除外する列」の条件値id
:除外する列。つまり「除外する値」とあわせると、これから更新しようとしているユーザーidに一致する列はユニークチェックの対象外となるdeleted_at
:追加条件の列名NULL
:前のd「追加条件の列名」の条件値。つまりこの場合、deleted_at = NULL
に該当するレコードに対してユニークチェックを行うことになる
この設定から、ユニークチェックの対象となるレコードを取得する際に発行されるSQLは次のようなイメージになります。
SELECT `email` FROM `users` WHERE `id` <> ${id}の値 AND `deleted_at` = NULL
補足
FormRequest
ではなくController
のメソッド内などで明示的にバリデーションを行いたい場合は、たとえば以下のようなコードになるでしょう。
public function update(Request $request) { $id = $request->input('id'); $request->validate([ 'email' => "unique:users,email,${id},id,deleted_at,NULL", ]); }
参考
公式ドキュメントにも、しっかりした説明とサンプルがあります。こちらもあわせて見てみましょう。
URLのバージョン部分(上の場合/5.6/)を、見たいバージョンに変更しましょうね。
コメント