ようこそゲストさん

CPA-LABテクニカル

2008/02/24(日) VALID_NOT_EMPTYの思わぬ動作。CakePHP1.2bバリデーション

CakePHP1.2は1.1に比べて、バリデーション(varidation,varidate)の大幅な機能強化が図られている。
ここでは、NOT EMPTY についてはまった点があったので覚書として書いておきます。
1.2bの話であって、1.1については知りません。

結論

値の要求 と 値が空かどうか のバリデーションは別個のものである。

通常、値が欲しいフィールドについて、

VALID_NOT_EMPTY を使う時には、必ず、'required'=>true を使用すること

(データベースのdefault値を設定していて、かつ、$this->Model->create($this->data);をバリデーションの前に実施している場合は、'required'=>trueはなくてもいいかも)

検証

$this->Model->validates()
関数が true を返すか、false を返すか。
全部、当てられる人がいたら、それはそれで恐ろしい。
'rule'=> VALID_NOT_EMPTY
が前提です。

他パラメータなし'required'=>true'allowEmpty'=>false,(参考)
'required'=>true
の理論上の動作
unsettrue ←attentionfalsetrue ←attentionfalse
nullfalsefalsefalsefalse
''falsefalsefalsetrue
\n(LF)falsefalsefalsetrue
\r(CR)truetruetruetrue
半角空白truetruetruetrue
全角空白truetruetruetrue
ゼロtruetruetruetrue
'00'turetruetruetrue
false(論理型)falsefalsefalsetrue
'false'(文字列型)truetruetruetrue
判別法正規表現'/.+/' ! isset+正規表現isset+empty
&not numeric+
正規表現
false になるもの正規表現'/.+/'と同等null値値がnullでなく、
emptyと評価される、
数値以外のもの。
留意点
'rule'=>VALID_NOT_EMPTY の場合の VALID_NOT_EMPTY は、定数で、「/.+/」と定義されていますので、要は正規表現だけで判別しているということです。

 混乱した点

 attentionの部分をみてください。
2つの場合で、 パラメータがセットされていない場合に、 true になっています。なぜかと調べると、この2つの場合は、
'allowEmpty'=>false と 'required'=>true のチェックをした後に、
array_key_exists($fieldName, $data)
というチェックで、unset の場合(キーが存在しない場合) には、そのまま 正規表現のループに入る前に、tureで処理を抜けてしまいます。
変数がセットされていれば、バリデーションの個々のルーチンに入るか、正規表現チェックを行います。
変数がセットされていない場合(キーが存在しない、unsetな場合)

'required'=>true の時には、 unset な変数は false となるのに、

'allowEmpty'=>false と VALID_NOT_EMPTY (&ただの正規表現だけの時も妥当する)

の時は、そのフィールドに設定された他のバリデーションルールを実行せずに、true を返す*1
という仕様になっています。


なるほど他の言語のバリデーションも、値の要求 と 値が空かどうか、 は全く別のものとして、考えられているようです。
私は、空でない値が欲しい = 値が空かどうか、 だけしか考えないことがはまった原因です。はい。

本当は
空でない値が欲しい  = 値の要求  + 値が空でない
となるわけですね。

 留意点

CakePHPのバリデーションの書き方はさまざまな書き方があって、それは、cakePHP 1.2のバリデーションを理解するが詳しいのですが、unset値も確実にerrorにしたい場合は、下記の簡便的な指定は避けた方がいいかと思います。
×
var $varidate = array(
' fieldname ' => VALID_NOT_EMPTY
);

留意点の留意点

通常、HTMLのフォームから入力された場合( input type="text" )、ユーザーが何も入力しなくても、空文字列'' はセットされますので、必ずしも、'required'=>true がなくても、通常の使用の範囲でなら、問題がでないことも多いかと思います。
(通常は、未定義の変数はフォームからはこない、という前提であるならば)


でも、悪意をもった人がPOSTしてきたり、chekboxの値*2などを取得するときは注意が必要かと思います。

留意点の留意点2

データベースのdefault値を設定していて、かつ、$this->Model->create($this->data);をバリデーションの前に実施している場合は、当該デフォルト値が、$this->Model->dataにセットされるので、変数が未定義のままバリデーションに突入する、ということはないかと思います。
その場合は、'required'=>trueは、なくても大丈夫かと思います。

参考にさせていただいたサイト

cakePHP 1.2のバリデーションを理解する
チェックボックスにチェックがない場合でもデータを送信する
Sun Limited Mt-CakePHP1.2 のバリデーション

*1 : 正しくはtrueを返すのではなく、errrorを設定しないという動作

*2 : CakePHPのフォームを使えば、どんな時でも空文字をセットしてくれるそうですが。。。


名前:  非公開コメント   

  • TB-URL  http://www.cpa-lab.com/tech/096/tb/