PHP
CakePHP
cakephp3
CakePHP 3Day 11

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

More than 2 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から読み込ん文字列のバリデーション

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