バリデーションとルール

バリデーション

リクエストデータがエンティティにコンバートされる前に、データ型や書式のルールが適用される。

<?php
$article = $articles->newEntity($this->request->getData());
if ($article->errors()) {
    // エンティティー検証失敗。
}
?>
エンティティ構築時のバリデーションの流れ
  1. バリデータオブジェクトが作成される
  2. table および default バリデーションプロバイダーが追加される
  3. 命名に沿ったバリデーションメソッドが呼び出される。たとえば validationDefault 。
  4. Model.buildValidator イベントが発動する
  5. リクエストデータが検証される
  6. リクエストデータがそのカラム型に対応する型に変換される
  7. エラーがエンティティーにセットされる
  8. 正しいデータはエンティティーに設定されるが、 検証を通らなかったフィールドは除外される

バリデータオブジェクトの作成

デフォルトのバリデータオブジェクト

デフォルトのバリデータオブジェクトはテーブル中でvalidationDefault()で作成される。

<?php
use Cake\ORM\Table;
use Cake\Validation\Validator;

class ArticlesTable extends Table
{
    public function validationDefault(Validator $validator)
    {
        $validator
            ->requirePresence('title', 'create')
            ->notEmpty('title');

        $validator
            ->allowEmpty('link')
            ->add('link', 'valid-url', ['rule' => 'url']);

        ...

        return $validator;
    }
}
?>
カスタムバリデータオブジェクト

カスタムバリデータ'update'の使用例。validationUpdate()メソッドで作成する。

<?php
class ArticlesTable extends Table
{
    public function validationUpdate($validator)
    {
        $validator
            ->add('title', 'notEmpty', [
                'rule' => 'notEmpty',
                'message' => __('タイトルを設定してください'),
            ])
            ->add('body', 'notEmpty', [
                'rule' => 'notEmpty',
                'message' => __('本文は必須です')
            ]);
        return $validator;
    }
}
?>

エンティティ作成時のオプションで'update'を指定。これでデフォルトのバリデータではなくupdateバリデータが適用される。

<?php
$article = $articles->newEntity(
    $this->request->getData(),
    ['validate' => 'update'] // バリデーションのオプション
);
?>
バリデータの組み合わせ

バリデータ作成メソッドの中で異なるバリデータを作成することで、バリデーションを組み合わせることができる。

<?php
public function validationHardened(Validator $validator)
{
    $validator = $this->validationDefault($validator); // デフォルトバリデータオブジェクトの作成

    $validator->add('password', 'length', ['rule' => ['lengthBetween', 8, 100]]);
    return $validator;
}
?>

ルール

データが保存される前に、ドメインルールまたはアプリケーションルールが適用される。
バリデーションはデータの構文や形式が正しいことを保証するのに対し、ルールはアプリケーションやネットワークの既存の状態に対してデータを比較することに焦点を当て、データの一貫性を保証する。

ルールチェッカーの作成

ルールチェッカーはテーブルクラスのbuildRules()で定義される。

<?php
use Cake\ORM\RulesChecker;

// テーブルクラスの中で
public function buildRules(RulesChecker $rules)
{
    // 作成および更新操作に提供されるルールを追加
    $rules->add(function ($entity, $options) {
        // 失敗/成功を示す真偽値を返す
    }, 'ruleName');

    // 作成のルールを追加
    $rules->addCreate(function ($entity, $options) {
        // 失敗/成功を示す真偽値を返す
    }, 'ruleName');

    // 更新のルールを追加
    $rules->addUpdate(function ($entity, $options) {
        // 失敗/成功を示す真偽値を返す
    }, 'ruleName');

    // 削除のルールを追加
    $rules->addDelete(function ($entity, $options) {
        // 失敗/成功を示す真偽値を返す
    }, 'ruleName');

    return $rules;
}
?>
一意性ルール

isUnique(['検証するフィールド'])でデータの一意性を検証する。

<?php
use Cake\ORM\Rule\IsUnique;

// 一つのフィールド
$rules->add($rules->isUnique(['email']));

// フィールドのリスト
$rules->add($rules->isUnique(
    ['username', 'account_id'],
));
?>
外部キールール

existIn('検証するフィールド', '参照先テーブル')でほかのリソースと関連づいているかどうか(外部キーに参照先テーブルのキーが入っているか)を検証する。

<?php
// 一つのフィールド
$rules->add($rules->existsIn('article_id', 'Articles'));

// 複数キー。複合主キーに役立ちます。
$rules->add($rules->existsIn(['site_id', 'article_id'], 'Articles'));
?>
アソシエーションカウントルール

一対多、多対多の関連があるとき、validCount('関連データ名', '件数', '比較演算子', 'エラーメッセージ')で関連データの件数を検証する。

<?php
// ArticlesTable.php ファイルの中で
// 記事にタグは5つ以内。
$rules->add($rules->validCount('tags', 5, '<=', 'タグは 5 つまで持てます'));
?>
ルールの無効化

エンティティ保存時にオプションでルールを無効化できる。

<?php
$articles->save($article, ['checkRules' => false]);
?>