CakePHP2で独自のバリデーション関数を定義する
CakePHP (2.4.x) には豊富なバリデーション用の関数が用意されていますが、たまには自分で定義したいこともあります。しかしドキュメントの日本語訳は整備されておらず(2013/11/20現在)原本を読みながら進めても、どうもハマりから抜け出せない。そんなことが続いたので解決法をメモしておきます。
どこに定義するか
- Modelクラス内(一番わかりやすい)
- しかし独自バリデーションが増えると肥大化し厄介
- 別の何かのクラス(ここで悩む)
今回は別の何かのクラスに定義する方法で進めます。
Behaviorを使う
英語版ドキュメントでは、'rule' => ['validationMethod', 'arg', 'className']
のようなことをしていたので、てっきりここでクラス名を指定するものかと思いきやこれは間違いでした。これは国別のローカライズに対応するためのものと判り、今回の独自関数の件とは全く別物です。
独自バリデーション関数を、Modelを肥大化させずにまとめておくにはBehaviorが便利でしょう。
class MyValidationBehavior extends ModelBehavior
{
// ルール定義
public static function rules()
{
$rules = [
'myField' => [
'myRule1' => [
'rule' => ['myMethod1', 'arg'],
],
'myRule2' => [
'rule' => ['myMethod2', 'arg', 'arg2'], // 複数記述しても使われない
]
],
];
return $rules;
}
// 独自バリデーション関数
public function myMethod1($model, $check, $arg) {
return true; // booleanを返す式
}
public function myMethod2($model, $check, $arg, $arg2) {
return true;
}
}
長ったらしいクラス名なんて嫌という方は、語尾のBehavior
のみ必須で、あとは自由に命名可能です。あまり頻繁に書くクラス名でもないので、私はFooValidationBehavior
と命名しています。
myMethod1($model, $check, $arg)
の記法は要注意で、第1引数の'
class MyModel extends AppModel
{
public $name = 'MyModel';
public $actsAs = ['MyValidation']; // ここで上記Behaviorを宣言
public function __construct()
{
parent::__construct();
if (isset($this)) {
$this->validate = MyValidationBehavior::rules();
}
return $this;
}
}
モデル側ではpublic $actsAs
の変数に配列でBehavior名を宣言します。このときCake側の規則によりBehavior
は不要です。
また、よくチュートリアルや解説ブログなどで、そのままpublic $validate = […];
としている例が多いですが、こうなると非常に配列のネストが深くなり不快なので、__construct()
を用意して、そこで代入しています。
管理を楽にするために独自バリデーション関数とルール定義はひとつのソース内に有ったほうがよいと考えました。
CakePHPは規則が多く微妙に不便と感じるところがありつつも、割となんとでもなるように作られているという印象です。複雑、肥大化しやすい部分はうまく切り分けて管理したいものです。
Discussion