2019/01/08更新

[Laravel] Uniqueバリデーションで、論理削除を考慮するなど、条件をカスタマイズしたい

このエントリーをはてなブックマークに追加            

こんにちは、@yoheiMuneです。
Laravelのバリデーションはそれだけで非常に強力ですが、ドキュメントには記載のない、拡張ポイントがあります。今日はUniqueバリデーションについて、拡張できるポイントをブログに書きたいと思います。



目次




何がしたいのか

Laravelのバリデーションの一つUniqueチェックを用いると、データベースのテーブルの指定したカラムで、値がユニークであるか(一意であるか)をチェックできます。例えば以下のように実装します。
$request->validate([
    // usersテーブルのemailカラムで一意チェック.
    'email' => 'unique:users'
]);
また、テーブルのどのカラムを用いて検査するのか、明示的に指定することもできます。
$request->validate([
    // usersテーブルの「mail_address」カラムで一意チェック.
    'email' => 'unique:users,mail_address'
]);
これだけでも非常に便利なのですが、時には検査対象を限定したい場合があります。例えば以下のような場合です。

  • 論理削除されたデータは、一意チェックの対象外にしたい。
  • (ユーザーデータ更新時に)自分のemailは一意チェック対象外にしたい。
  • (何か会社という組織があったとして)会社の中でemailを一意にしたい(他の会社には同一emailがあってもOK)。

それらに対応できるような拡張ポイントが、Laravelでは用意されています。今日はそれをブログに書きたいと思います。



論理削除データを、一意チェックの対象外にしたい

以下のようにして、論理削除されたデータを除外して、一意チェックすることができます。
// インポートを追加.
use Illuminate\Validation\Rule;

$request->validate([
  // usersテーブルのemailカラムについて、
  // deleted_atがnullのレコードを対象に、一意チェックする.
  'email' => [Rule::unique('users', 'email')->whereNull('deleted_at')]
]);
ここではdeleted_atがnullのレコード(つまり論理削除されていないレコード)のみをチェック対象としています。



自分のemailアドレスはチェック対象外にしたい

一意チェックに、除外条件も追加できます。ここではwhereNotを利用します。
// インポートを追加.
use Illuminate\Validation\Rule;

// 自分のメールアドレス.
$myEmail = Auth::user()->email;

$request->validate([
  // usersテーブルのemailカラムについて、
  // 「email != $myEmail」のレコードに対して、一意チェックを行う.
  'email' => [Rule::unique('users', 'email')->whereNot('email', $myEmail)]
]);
これで自分のメールアドレスを、チェック対象外にできます。



会社の中でemailを一意にしたい

whereを用いることで、対象を絞って一意チェックを行うこともできます。
// インポートを追加.
use Illuminate\Validation\Rule;

// 会社ID.
$companyId = Auth::user()->company_id;

$request->validate([
  // usersテーブルのemailカラムについて、
  // 「company_id = $companyId」のレコードに対して、一意チェックを行う.
  'email' => [Rule::unique('users', 'email')->where('company_id', $companyId)]
]);
このように自由に対象を絞ることができます。便利ですね。



requiredなど、他のバリデーションと組み合わせる

他のバリデーションと組み合わせて、使うこともできます。利用したいバリデーションを、配列形式で指定します。
$request->validate([
  // bail, required, email, unique を指定して値のチェックを行う.
  'email' => ['bail', 'required', 'email', Rule::unique('users', 'email')->whereNull('deleted_at')]
]);
ここではbailrequiredemailuniqueを配列で指定することで、複数のバリデーションを実現しています。



さらに詳しく

今回紹介した機能は、illuminate/validationの実装にあります。Unique.phpDatabaseRule.phpの実装を読むと他にも、whereInなどがあることがわかります。



最後に

Laravelは、調べれば調べるほどに色々な機能が見つかって楽しいなぁと感じる今日この頃です。Laravelでの開発をたくさんしていてノウハウもたまってきたので、ブログにもドシドシと書けたらと思います。

最後になりますが本ブログでは、PHP、フロントエンド、Python、サーバー、インフラ、Swift、Node.js、Java、Linux、機械学習、などの技術トピックを発信をしていきます。「プログラミングで困ったその時の、解決の糸口に!」そんな目標でブログを書き続けています。ぜひ、本ブログのRSSTwitterをフォローして貰えたら嬉しいです ^ ^

最後までご覧頂きましてありがとうございました!





こんな記事もいかがですか?

RSS画像

もしご興味をお持ち頂けましたら、ぜひRSSへの登録をお願い致します。