結論から言うと、cakephp(version = ‘1.2.3.8166′)でmysqlのtinyint型に対してModel->save()によるinsertをする場合、強制的にその型はboolean(結果的には0 or 1)にキャストされます。
これで4時間ぐらいはまった・・・ので、怒りに任せてエントリーw
以下、ハマるポイントの詳細。
気づき
まず、こんなテーブルに対して、
`id` int(9) NOT NULL auto_increment,
`body` text,
`type` tinyint(1) default NULL,
`created` datetime default NULL,
`modified` datetime default NULL,
PRIMARY KEY (`id`)
) ;
ごく普通に新規登録する処理を実装しました。ポイントはtypeカラムがtinyint(1)なことです。その登録処理はこんな感じ、
(・・・省略・・・)
$this->data['Comment']['type'] = 2;
if (!$this->Comment->save($this->data)) {
// SQLエラー処理
}
(・・・省略・・・)
Commentモデルのtypeには「2」を固定でセットしています。これで、typeカラムに「2」が登録されると思っていたのですが、登録されたデータを見てみると「1」になってました。。。はにゃ?とおもい、実行されるSQLを見てみると、
となっており、typeの値が1になっています。なんで!なんでなのっ!
ということで、ここからがハマリタイム(というか、この辺を意識しないで書けるのがcakephpの特徴なのに・・・うう・・・TT)。
調査
ソースを追いかけ、紆余曲折しながら、分かったことは、どうやら、typeカラムがbooleanとして扱われているということでした。
ソースでいうとこの辺(/cake/libs/model/datasources/dbo/dbo_mysql.phpの496行目らへん)
(・・・省略・・・)
switch ($column) {
case 'boolean':
return $this->boolean((bool)$data);
break;
(・・・省略・・・)
つまり、$this->data['Comment']['type']に1だろうが2だろうがstring型を入れようが、booleanにキャストされるもんで、結果的に0or1しか入らないわけです。。。
他にもtinyintなカラムはあったんですが、これまで0or1しか登録してなかったので、気づきませんでした。てか、勝手にbooleanにしないで・・・涙。
対策
このtypeカラムには1桁の数値が入る予定だったので、tinyintが使えないならということでsmallintに変えました。変えてから上の登録処理を実施すると、無事期待通りのSQLが実施されました。
再び結論
tinyint型はbooleanとして扱われるぞぉー気をつけろぉーー
あ、ちなみにupdateのときはどうなるかは未検証ですが、おそらくおんなじ結果じゃないかなぁーと思ってます。
冷静になって、同じ現象を検索してみると、やはりありました。
[k]zi.bz:CakePHPトtinyintトboolean
もう一歩さきを調べられており、勉強になりました。
|
cakephp、mysqlのtinyint型に注意