Help us understand the problem. What is going on with this article?

CakePHP3のバリデーションは2度動く!

More than 3 years have passed since last update.

CakePHP3のバリデーションは2度動く!

CakePHP2の時は save でバリデーションが実行されてましたね。

もちろんCakePHP3でも save でバリデーションが実行されますが、
2種類のバリデーション実行タイミングがあります。

どこで実行されるの?

1個目が以下のように newEntitypatchEntity にPOST値等のデータを与えて Entity を作ったタイミングでバリデーションが実行されます。

$entity = $table->newEntity($data);
$patchEntity = $table->patchEntity($entity, $data);

注意するポイントとしては、バリデーションに引っかかった項目は 戻り値の Entityに反映されません

バリデーションの記述場所

// src/Model/Table/HogeTable.php

// ここにEntity作成時のバリデーションを記述します。
public function validationDefault(Validator $validator)
{
    $validator
        ->add('id', 'valid', ['rule' => 'numeric'])
        ->allowEmpty('id', 'create');

    $validator
        ->allowEmpty('title');
}

バリデーションに引っかかったかのチェック

以下のように Entityのerrors メソッドを実行することでエラーの一覧を取得できます

※手動で実行しなくても、save 実行時に自動的に実行されます。

$entity = $table->newEntity($data);
$entity->errors();

    or 

$table->save($entity);  // <-- return false

save時のバリデーションはどこに記述すればいいの?

以下のように buildRules にsave時のバリデーションを記述します。

// src/Model/Table/HogeTable.php

public function buildRules(RulesChecker $rules)
{
    // タイトルにテストという文字を許可しない
    $rules->add(function ($entity, $options) {
        if ($entity->title != 'テスト') {
            return true;
        } else {
            return false;
        }
    }, 'test', [
        'errorField' => 'title',
        'message' => '「テスト」は登録することが出来ません'
    ]);

    // HogeTableクラス内のcheckStatusメソッドを実行
    $rules->add([$this, 'checkStatus'], 'status', [
        'errorField' => 'status',
        'message' => 'ステータスが有効ではありません'
    ]);
}

バリデーションに引っかかったかのチェック

バリデーションに引っかかった場合は、save メソッドがfalseを返します。

バリデーションエラーの中身を確認したい場合は、 Entity作成時と同じ Entityのerrors を使用します。

まとめ

  • POST入力値等の入力値チェックは validationDefault に記述する
  • saveの入力値チェック(Entityチェック)は buildRules に記述する
     
    CSVアップロードからのデータ登録のような状況であれば
    • validationDefault でCSVファイルのフォーマットチェック
    • buildRules でCSVから読み込ん文字列のバリデーション

というように明示的にバリデーションを切り分けることが出来るのでうまく使えば可読性を高めることが可能になります!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした