CakePHPでbool解釈されたデータをnotEmptyチェックすると、エラーになることがある件

【現象】

CakePHPのmodelを利用して、tinyint(1)で定義したカラムを読み込むとbool型として読み込まれる。
これまでは特に気にしていなかったが、、このデータをfindByIdで読み込んで、、そのまま、setして保存すると、、、
カラムに対して、validateを設定していない場合は成功するが、validate設定(notEmpty)している場合に中身がfalseだと失敗することが発生。。。
いやいや、boolで判別してるのはCakeさんですよね。。。と、言いつつ、不可解なのでコードを読んでみた。

【見たところ】

1. /lib/Cake/Utility/Validation.phpのnotEmpty。
実際の値チェックがされているnotEmptyをまず確認。_check前の事前確認では問題なし。

	public static function notEmpty($check) {
		if (is_array($check)) {
			extract(self::_defaults($check));
		}
		if (empty($check) && $check != '0') {
			return false;
		}
		return self::_check($check, '/[^\s]+/m');
	}

2. /lib/Cake/Utility/Validation.phpの_check。
正規表現で値をチェックする_check。

	protected static function _check($check, $regex) {
		if (is_string($regex) && preg_match($regex, $check)) {
			return true;
		}
		return false;
	}

ここでエラー。trueの場合成功するのも謎なんですが、とりあえずfalseになる箇所は発見。

3. テストコードで調べる
簡単なコードを作り、$tmpValueの中を変化させて確認。

$tmpValue = false;
if (preg_match('/[^\s]+/m', $tmpValue)) { echo "OK"; } else { echo "NG"; }
...NG
$tmpValue = 0;
if (preg_match('/[^\s]+/m', $tmpValue)) { echo "OK"; } else { echo "NG"; }
...OK
$tmpValue = '';
if (preg_match('/[^\s]+/m', $tmpValue)) { echo "OK"; } else { echo "NG"; }
...NG
$tmpValue = null;
if (preg_match('/[^\s]+/m', $tmpValue)) { echo "OK"; } else { echo "NG"; }
...NG
$tmpValue = true;
if (preg_match('/[^\s]+/m', $tmpValue)) { echo "OK"; } else { echo "NG"; }
...OK

いまいちピンときませんでした。が、preg_matchの定義を改めて見てみると、

int preg_match ( string $pattern , string $subject [, array &$matches [, int $flags = 0 [, int $offset = 0 ]]] )

チェック前に、文字列変換してやってるのか?、、と、考え、、もうひとつ確認。

$tmpValue = true;
var_dump(strval($tmpValue));
... string(1) "1" 
$tmpValue = false;
var_dump(strval($tmpValue));
... string(0) "" 

これか。。これなのか。これだと、最初のテストコードで、、”の場合にNGになったのと合います。

【多分結論】
・CakePHPではtinyint項目をboolとして読み込む
・PHPでは、bool値を文字列変換すると、true => 1, false => ”と変換される
・notEmptyの項目は最終的にpreg_matchを使って判定され、その過程で、おそらく判定対象の値がstring変換される。結果、falseは上記とおり”に変換されてしまい、emptyとして判定される。。。
※罠1。tinyintをboolに勝手に変換してくれる。
※罠2。trueは1だから、falseは0とかなんとなく想定していたらfalseは”。(どうせならtrueも”にてくれれば、、わかりやすいのに)

【回避策】
回避方法としては、、DBから読み込んだ値をそのまま使わずに、0/1を設定してあげるか、、validateをはずしてあげるか、、ぐらいしか思いうかばず。
自分の知識の無さもふまえても、なんだかなーって結果でした。

追記(2014.04.15)

指摘されて、、確認したところ、CakePHPにはbooleanというvalidationルールがありました。
notEmptyではなく、booleanで定義したところ、、問題なく動作。

	'boolean' => Array(
		'rule' => Array('boolean'),
		'message' => '指定してね',
		'required' => true,
	)

結果、文字列でない値にnotEmptyを使っていた私が、、、知識不足ということでした。CakePHP様申し訳ございません、。