概要
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/)を、見たいバージョンに変更しましょうね。


コメント