おかか梅干し

白米が好きすぎる

Validatorに 複数フィールドで重複チェックを追加したい

あるテーブルのデータを保存するときに、Validatorに重複チェックを追加したい。
ユーザデータを登録する時に、ユーザIDやメールアドレスなど、1フィールドに対する重複チェックはよくある。
今回はそうではなくて、複数フィールドをキーとして、重複チェックをしたい。

たとえば、「1ユーザが1カテゴリーに付き1件の記事を投稿できる」という仕様があったとして、
記事TBLに、「ユーザID、カテゴリID、日付」この3フィールドで重複チェックをかけたい、みたいな時の話。

公式ではbuildRulesでのルールの書き方しか載っていなかった。

book.cakephp.org

なんで、buildRulesでのやり方しか載っていないのかと思ったが、こちら↓のページが参考になった。

validation - CakePHP 3.xの一意の検証が複数のレコードの保存に機能しない - ITツールウェブ

要は、検証(Validation)中はまだ保存もされてないので、データの存在保証ができない。とくに、saveMany() などでいっぺんにデータを保存する時などがそれ。
重複など確実に検証したいときはsaveの直前、buildRulesでやるのが正解なのだろう。

でも今回は、データ登録時の検証だけでなく、登録前のデータ確認画面で重複チェックをしたかったので、色んな所で利用できるValidatorで実装したかった。

環境や仕様

Validator書き方

  • Model/Table/ArticleTable.php
    /**
     * validationExistingData
     *
     * 登録済みのデータが有るか?
     *
     * @param \Cake\Validation\Validator $validator Validator instance.
     * @return \Cake\Validation\Validator
     */     
    public function validationUniqueData(Validator $validator)
    {
        $validator
            ->add('category_id', 'validationUniqueData',[ //'validationUniqueData'は任意の名前
                'rule' => [
                    'validateUnique',
                    ['scope' => ['user_id', 'create_date']]
                ],
                'provider' => 'table',
                'message' => 'そのカテゴリの記事はすでに存在します。',
            ]);

        return $validator;
    }
  • Controller/ArticleController.php
$params = [ // $this->getRequest()->getData()
    'category_id' => 1,
    'user_id' => 1,
    'create_date' => '2021-03-19',
];

$errors = $this->Article->getValidator('UniqueData')->errors($params)

こんな感じ。