Home > CakePHP | PHP > CakePHP モデルのvalidates()に注意

CakePHP モデルのvalidates()に注意

この記事の所要時間: 138

Model#validates()ですが、「ちょっとどうなの?」な仕様になってます。

このメソッドはModel#save()内で自動的に呼ばれるのか、コントローラのアクションメソッド内で呼ばれるのが一般的な使い方だと思います。

問題が起こるのは後者の方で、空の配列をvalidates()に渡すと、Userl#$validateで何を定義していてもtrueが返ってきます。

下のソースならUserモデルの$validateに入力チェックをいれておけば「ng」が表示されそうですが、実はUser#$validateに関わらず「ok」が表示されてしまいます。

<?php
class FooController extends AppController
{
    var $uses = array('User');

    function blank()
    {
        $this->data = array();
        if ($this->User->validates($this->data)) {
            var_dump('ok');
        } else {
            var_dump('ng');
        }

        exit;
    }
}
?>

原因はModel#invalidFields()の以下の箇所にあります。(invalidFields()はvalidates()から呼ばれます)

[cake/libs/model/model_php4.php]

<?php

		foreach($this->validate as $field_name => $validator) {
			if (isset($data[$field_name]) && !preg_match($validator, $data[$field_name])) {
				$this->invalidate($field_name);
			}
		}

?>

$dataはvalidates()に渡される連想配列なのですが、$dataに$validateのキーが存在しない場合はpreg_match自体が処理されず、invalidate()にはなりません。

なのでコントローラからvalidates()を呼ぶ時は、$dataにModel#$validateのキーに存在するかを確認する必要があります。

ちなみにModel#save()ではvalidates()の後の処理でfalseが返るようになっています。ただこれも$dataが空の配列の場合の話で、Model#$validateにキーは無い(入力チェックはしない)が、テーブルにカラムがあるキーのみの配列なら通ってしまいます。

例えば下のソースなら「ok」が表示されます。

<?php
    function blank()
    {
        // User#$validate に id が無い場合
        $this->data = array('id' => '');
        if ($this->User->save($this->data)) {
            var_dump('ok');
        } else {
            var_dump('ng');
        }

        exit;
    }
}
?>

やはりこちらも入力チェックするキーが$dataに存在するかを確認するしか無いようです。

Pocket

follow us in feedly

コメント (Close):6

yando 07-04-27 (金) 9:33

必須項目のキーをプロパティに設定しておき、validatesの際に存在チェックを事前に行うようにオーバーライドですかねー。

shinbara 07-04-27 (金) 9:42

@yandoさん
ですね。

はじめAppModel#beforeValidate()でそれをやろうと考えたのですが、Model#saveField()の時に困るんですよね。
users.statusだけ変えたいのにusers.nameのバリデートに引っかかるとか。
多分saveField()のためにこんな仕様になってるんでしょうね。

slywalker 08-12-04 (木) 21:52

array(
‘rule’ => array(‘notempty’),
‘required’ => true,
),
);
}
?>
上記のように、’required’ => true で’ng’でました!
さらに、saveFeildも試しました。
$this->User->saveField(‘password’, ‘hoge’)
問題なく保存できました!

slywalker 08-12-04 (木) 21:54

すいませんコード部分が消えたので補足です^^;

var $validate = array(
‘name’ => array(
‘rule’ => array(‘notempty’),
‘required’ => true,
),
);

slywalker 08-12-04 (木) 22:17

2007/04/26 17:58
思いっきり日付を勘違いしていました。
はてブの新着エントリーにあったので・・・
_| ̄|○

arimaster 09-02-17 (火) 13:02

slywalkerさんのやり方を参考にさせて頂いたのですが、
私の方ではなぜか必ずfalseになってうまくいきませんでした・・・。

こちらのサイト(http://tech.li-pton.com/php/validation_trap.html#)を参考に
「createメソッドでデータをセットし、validatesメソッドは引数なしで呼び出す」とうまくいきました。

if($this->User->create($this->data) && $this->User->validates()){

}else{

}

トラックバック:2

このエントリーのトラックバックURL
http://www.1x1.jp/blog/2007/04/cakephp_model_validates.html/trackback
Listed below are links to weblogs that reference
CakePHP モデルのvalidates()に注意 from Shin x blog
pingback from sylvan :: 対応が必要なモデルの validates 07-11-05 (月) 16:25

[…] CakePHP モデルのvalidates()に注意 | Shin x blog には対応する必要がありそう。 […]

pingback from cakephpのvalidates()メソッドが動かない | PLIME – tech 10-09-20 (月) 1:54

[…] 【CakePHP モデルのvalidates()に注意】 【validates()とinvalidate()の記述順】 […]

Home > CakePHP | PHP > CakePHP モデルのvalidates()に注意

検索
フィード
メタ情報

Return to page top