CakePHP 動的なバリデーションの変更

バリデーションの必須項目の動的変更

モデルで定義したバリデーションルールを、コントローラから動的に、必須項目の設定(‘required’=>true)を追加、削除できるコードが紹介されています。フィールド単位で、必須項目を削除(remove)、または、残す(keep)ことができるようです。

Simple Way to Unbind Validation & Set Remaining Rules to Required

「英語を読むのがつらい…」という方の為に、簡単に使い方を説明します。

1-1. app_model.php を作成

app/modeles フォルダ内に、app_model.php ファイルを作成して、以下のコードをコピペします。

<?php
class AppModel extends Model {
	function unbindValidation($type, $fields, $require=false) {
		if ($type === 'remove') {
			$this->validate = array_diff_key($this->validate, array_flip($fields));
		} else if ($type === 'keep') {
			$this->validate = array_intersect_key($this->validate, array_flip($fields));
		}
		if ($require === true) {
			foreach ($this->validate as $field=>$rules) {
				if (is_array($rules)) {
					$rule = key($rules);
					$this->validate[$field][$rule]['required'] = true;
				} else {
					$ruleName = (ctype_alpha($rules)) ? $rules : 'required';
					$this->validate[$field] = array($ruleName=>array('rule'=>$rules,'required'=>true));
				}
			}
		}
	}
}
?>

1-2. モデルにバリデーションルールを記述

使用するモデル(Entryとします)に、普段どおりバリデーションルールを記述します。

<?php
class Entry extends AppModel {
	public $name = 'Entry';
	public $validate = array (
		'name' => array (
			'rule' => array('notEmpty'),
			'required' => true,
			'message' => '名前が入力されていません'
		)
	);
}
?>

※バリデーションルールを ‘rule’ => ‘notEmpty’ と記述するとエラーになりますので、‘rule’ => array(‘notEmpty’) と記述しましょう。CookBookによると、‘rule’ => ‘notEmpty’ と記述することになっていますが、’rule’ => array(‘notEmpty’) でも動くようですね。。もちろん、‘rule’ => array(‘notEmpty’, ‘numeric’) のように、複数のルールを1行で定義することはできませんのでご注意を。

1-3. コントローラ側で動的に制御する

コントローラ側で、バリデーションを行う前に、以下コードを記述します。

$this->Entry->unbindValidation('remove', array('name'), true);

‘name’ フィールドのバリデーションの必須項目が削除(’remove’)され、空の値でも許可されるようになります。

バリデーションルールの動的な変更

前述のコードは、フィールド単位で制御する方法でした。
一方、1つのフィールドに複数のバリデーションルールが設定されていて、その中の特定のルールだけを変更したい場合はどうすればよいでしょうか?

難しく考えなくても、いたってシンプルです。
バリデーションルールを上書きしてしまえば良いのです。

電話番号を入力させる ‘tel’ というフィールドを用意したとします。
半角数字のみを許可する ‘numeric’ はディフォルト。
そこに、入力必須の ‘notEmpty’ のルールをコントローラ側で動的に設定(追加)する方法を考えます。

まず、モデルには ‘numeric’ のルールを設定しますが、‘allowEmpty’ => true で空入力を許可しておきます。
これで、入力値がある場合のみ ‘numeric’ のバリデーションが働きます。

[モデル]

public $validate = array (
	'tel' => array(
		'numeric' => array(
			'rule' => 'numeric',
			'allowEmpty' => true,
		),
	),
);

次に、コントローラ側で動的に入力必須のルールを追加します。
バリデーションを行う前に、’tel’ のバリデーションルールを上書きしてしまいます。

[コントローラ]

$this->Entry->validate['tel'] = array(
	'numeric'=> array(
		'rule' => 'numeric',
	)
);

‘allowEmpty’ => true が外れたので、実質、入力必須になるというわけです。

この方法がわかればあとは簡単ですね。
いくらでも動的にバリデーションルールを変更することが可能です。

動的にバリデーションルールを変更するフィールドについては、ディフォルトでバリデーションルールを設定しないフィールドであっても、モデル側でそのフィールドの空のバリデーション配列を用意しておかなければならない点に注意してください。

public $validate = array (
	'tel' => array(
	),
);

コメントを残す