あっぽログ
← 記事一覧に戻る

CakePHPのバリデーション入門:ルールの定義からカスタムバリデーションまで使いこなす

はじめに

Webアプリケーションでは、ユーザーからの入力値が正しい形式かどうかを確認する「バリデーション(入力値検証)」が欠かせません。CakePHPには強力なバリデーション機能が組み込まれており、少ないコードで多彩なルールを適用できます。

この記事では、CakePHPのバリデーションの基本的な仕組みから、カスタムルールの作成、エラーメッセージのカスタマイズまでを順番に解説します。


バリデーションの基本構造

CakePHPのバリデーションは、主に TableクラスvalidationDefault() メソッドに記述します。Validatorオブジェクトにルールをチェーンして追加していくスタイルです。

// src/Model/Table/UsersTable.php

namespace App\Model\Table;

use Cake\ORM\Table;
use Cake\Validation\Validator;

class UsersTable extends Table
{
    public function validationDefault(Validator $validator): Validator
    {
        $validator
            ->notEmptyString('username', 'ユーザー名は必須です')
            ->minLength('username', 3, 'ユーザー名は3文字以上で入力してください')
            ->maxLength('username', 20, 'ユーザー名は20文字以内で入力してください');

        $validator
            ->email('email', false, 'メールアドレスの形式が正しくありません')
            ->notEmptyString('email', 'メールアドレスは必須です');

        $validator
            ->minLength('password', 8, 'パスワードは8文字以上で入力してください')
            ->notEmptyString('password', 'パスワードは必須です');

        return $validator;
    }
}

notEmptyStringemail などのメソッドは、CakePHPがあらかじめ用意しているビルトインルールです。引数にはフィールド名、続いてオプション、エラーメッセージを渡すのが基本パターンです。


よく使うビルトインルール

CakePHPにはさまざまなビルトインルールが用意されています。代表的なものを確認しておきましょう。

$validator
    // 必須チェック
    ->requirePresence('title', 'create', 'タイトルフィールドは必須です')
    ->notEmptyString('title', 'タイトルは空にできません')

    // 数値・範囲チェック
    ->integer('age', '年齢は整数で入力してください')
    ->range('age', [0, 120], '年齢は0〜120の範囲で入力してください')

    // 文字列長チェック
    ->maxLength('bio', 200, '自己紹介は200文字以内にしてください')

    // 正規表現チェック
    ->regex('phone', '/^\d{10,11}$/', '電話番号は10〜11桁の数字で入力してください')

    // URL チェック
    ->url('website', false, 'URLの形式が正しくありません')

    // 日付チェック
    ->date('birthday', ['ymd'], '日付はYYYY-MM-DD形式で入力してください');

requirePresence はリクエストにそのフィールド自体が存在するかを確認するルールで、第2引数に 'create'(新規作成時のみ)や 'update'(更新時のみ)を渡すことで場面に応じた検証が可能です。


カスタムバリデーションルールの作成

ビルトインルールでは対応できない要件には、独自のバリデーションルールを作成します。add() メソッドにクロージャを渡すのが最もシンプルな方法です。

$validator
    ->add('username', 'noSpaces', [
        'rule' => function ($value, $context) {
            // スペースを含む場合はfalseを返す
            return strpos($value, ' ') === false;
        },
        'message' => 'ユーザー名にスペースは使用できません',
    ])
    ->add('username', 'reservedWords', [
        'rule' => function ($value, $context) {
            $reserved = ['admin', 'root', 'system'];
            return !in_array(strtolower($value), $reserved, true);
        },
        'message' => 'そのユーザー名は使用できません',
    ]);

$context 引数には、現在のエンティティデータや操作の種類(newRecord か否か)などが含まれます。他フィールドの値を参照したい場合に活用できます。

$validator
    ->add('password_confirm', 'matchPassword', [
        'rule' => function ($value, $context) {
            // passwordフィールドと一致するか確認
            return isset($context['data']['password'])
                && $value === $context['data']['password'];
        },
        'message' => 'パスワードが一致しません',
    ]);

複数のバリデーションセットを使い分ける

CakePHPでは、新規作成用・更新用など場面ごとに異なるバリデーションセットを定義できます。

// 更新用のバリデーションセットを追加
public function validationUpdate(Validator $validator): Validator
{
    $validator
        ->notEmptyString('email', 'メールアドレスは必須です')
        ->email('email', false, 'メールアドレスの形式が正しくありません');

    // パスワードは任意(空なら変更しない)
    $validator
        ->allowEmptyString('password')
        ->minLength('password', 8, 'パスワードは8文字以上で入力してください');

    return $validator;
}

コントローラー側では patchEntity() の第3引数でセットを指定します。

// src/Controller/UsersController.php

// 更新時はvalidationUpdateセットを使用
$user = $this->Users->patchEntity(
    $user,
    $this->request->getData(),
    ['validate' => 'update']
);

バリデーションエラーの取得と表示

コントローラーでエラーを確認し、Viewに渡すのが一般的な流れです。

// コントローラーでエラー確認
if ($this->Users->save($user)) {
    $this->Flash->success('保存しました');
    return $this->redirect(['action' => 'index']);
}

// エラーがある場合はそのままViewへ(エラーは$userに紐づく)
$this->Flash->error('入力内容を確認してください');

Bladeのような独自テンプレートではなく、CakePHPのテンプレートでは FormHelper を使うとエラーが自動で表示されます。

// テンプレート(templates/Users/add.php)
echo $this->Form->create($user);
echo $this->Form->control('username', ['label' => 'ユーザー名']);
// バリデーションエラーが自動的にフィールド下に表示される
echo $this->Form->control('email', ['label' => 'メールアドレス']);
echo $this->Form->control('password', ['type' => 'password', 'label' => 'パスワード']);
echo $this->Form->button('登録');
echo $this->Form->end();

FormHelper::control() はエンティティに紐づいたエラー情報を自動的に読み取り、CSSクラスの付与やメッセージ表示を行ってくれます。


まとめ

CakePHPのバリデーション機能のポイントをまとめます。

  • validationDefault() にルールを記述するのが基本
  • notEmptyStringemail などの ビルトインルール が豊富に用意されている
  • add() にクロージャを渡すことで カスタムルール を自由に定義できる
  • $context を使うと 他フィールドの値を参照 したルールも書ける
  • 複数の バリデーションセット を定義して場面ごとに使い分けられる
  • FormHelper と組み合わせるとエラー表示が自動化される

バリデーションを適切に実装することで、不正なデータの混入を防ぎ、アプリケーションの安全性と品質を高めることができます。ぜひ実際のプロジェクトで活用してみてください。

← 記事一覧に戻る