saveとちがい、updateAllは、クオートされないので、sqlをそのまま使える。はず。


  1. $model->updateAll(array ('column'=>'CASE WHEN column='a' THEN 'b' ELSE 'c' END'))

は、

  1. UPDATE `model` SET `column`=1 WHERE 0=1

となってしまう。

ゆっくりデバッグしていくと、


  1. $fields = $this->_prepareUpdateFields($model, $combined, empty($conditions), !empty($conditions));

cake/libs/model/dbo_mysql.php 143行目に


conditionsが空の場合、_prepareUpdateFieldsにて、fieldの値が、エスケープされてしまう。

なので、特にコンディションがなくても、 array(1=>1)とかってやると、そのままの値が使われる。

うーん。

どうしてもsubversionのレポジトリを、外部と共有しなくてはいけなくなって、webdav+svn on virtualhostでと。

外部への公開が済んで、今度はLAN内の別のhostから取得しようと。。。


svn: PROPFIND リクエスト (相手: '/repo/trunk') がしっぱいしました
svn: PROPFIND (URL: '/repo/trunk'): 501 Not implemented (http://unchoko.net)


virtualホストの設定をいじったり、何やってもダメ

ふと、リクエストするurlを変更しても、同じエラーが発生。。。。ん?

そうなのだ、Lan内からルータの外側アドレスにアクセスしていたのだwww

だから、ルーターのHTTPサーバへアクセスしていることになり、「メソッドが存在しない」501エラーが発生していたのだ。

で、LAN内の名前でアクセスして、無事checkout出来たとさw


1時間はまった

順調に趣味のサイトをcakePHPにて開発しいたが、どうしてもsave関連のメソッドの挙動が気にくわない

save($data)

$data中にprimary_keyが存在すればupdate, 無ければinsert
で、insertの方には問題がないが、updateの場合は$data[id]がテーブル上に存在し無ければ、insertしてくれるというお節介を起こす。

update前に、SELECT COUNT(*) FROM MODEL WHERE ID=IDって問い合わせしている。
そもそもUPDATE後に、affected_rowsで調べるのでは、ダメなんだろうか?

例えば、find, read等で行を取得。
テーブルをLOCKした上で、取得したなら問題ないが、save等で保存するまでの間に、該当行が削除されてしまった場合、予想外にinsertされてしまう。

これは、saveFieldでも同じ。

確かにsaveという響きから想像できる挙動ではあるが、出来ればprimary keyがある場合で、idが存在しないならfalseを返してほしい。

save後に、Model->idへ該当IDが入るので、元のデータと比較すれば、updateされたのか?insertされたのかを検査する事は出来る
insertされた場合には、元のデータのidとは違うlastInsertIdになっている。

でも、面倒だからupdateAllを使うけどね


あと、戻り値

例えば、

if ( Model->save($data) ) {
 print 更新しました
}

もしくは
if ( !Model->save($data) ) {
print 失敗だよ
}

って書いてはいけない!!

なぜなら、$dataの配列が正確でなかった場合、insertもupdateもされずに、trueが返ってしまうのだ。

正確にinsert,もしくはupdateされた場合は、created等が補完された
[Model] => array( id => 1, created=> datetime, field => ・・・

的な配列が返る

なので、 is_arrayで検査しないといけない
falseが返るのは、sqlエラーが発生した時だけなので注意が必要だ。
saveでは、primary key以外の
unique違反でしか発生しないかな?


でも、save、saveFieldメソッド、便利な感じなんだけどね~

INSERTする以外は、使えそうにない。

saveAllは、また戻り値が複雑。
optionのatomic = true(デフォルト)の場合、成功すればtrue, 失敗は空の配列が返る。
しかし他でModel->begin()している場合には、atomic = falseとしてsaveAllを呼ぶが、その場合の戻り値は、array(Model => true, Model => false)といった感じになるのだ。
なので、atomic = falseとした場合は、戻りを検査しないといけない。

cakePHPの公式サイトは親切でそれなりに充実しているが、ほとんど戻り値に関してふれられていない気がするんだが。。
意外に情報がないのだけど、みんな、どうしてるんだろw。



関係ないグチ

プログラマーといっても、そのレベルはピンキリだ。
以前、メールアドレスを検証するコードで、

for ( $i = 0; $i < strlen($address); $i++ ) {
$moji = substr($address, $i, 1);
if ( $moji == '@' && $i == 0 ) {
return false;
} elseif ( $moji == 'a' ・・・・使える記号へ続く・・・

} else {
return false; //上のリスト以外の文字
}
ってコードを見た時は大爆笑したww
ってゆーか、変数名$mojiってなんだよwww$strとかあるじゃんw

もっとシンプルな方法があるはずだ!って思考出来ないのだ

この手のタイプは何事においても検証しないので、結果、穴だらけのプログラムが放置される。

でも、結構この手のタイプが、プログラマとして使い物にならないので、偉くなったりするwww

そして、優秀なプログラマーのモチベーションを奪うんだなぁーw