CakePHPでデータ削除

この記事はCakePHP1.2向けです。
CakePHPでテーブルから1行削除するときには、del()を使います。

$r1 = $this->Model->del($id);  //$id => 行のid

もしくは、DELETE文を書いて、query()かexecute()を使う。

$sql = 'DELETE FROM model WHERE id = 10';
$r2 = $this->Model->execute($sql);

では、上記の2つの方法の違いはなんだろうか?
それをまとめておく。

1. 戻り値

上の例で、$r1と$r2の関係性を整理しておこう。

関数 delete 成功 失敗
del r1 true false
execute r2 array() array()

executeではDELETEが成功したのか、失敗したのかを判定する方法がない。
これでは、トランザクション処理中に「もしDELETEが失敗したときにロールバックする」みたいな処理ができない。
これを解決する方法は調べたが、よくわからないので、ロールバックしなければいけないようなときは、del()を使いたいです。
問題 => execute()だと、成功と失敗をうけとることができない。

2. SQL

SQLにも違いがある。
execute()はもちろん、書いたSQLが実行される。
del()では、cakePHPがDELETE文を生成してくれるわけだが、
モデル内でbelongsToやhasOneなどでアソシエーションを指定していると、
アソシエーションしているテーブルをJOINしてしまうようです。

DELETE FROM model AS Model
LEFT JOIN model2 AS Model2 Model.model2_id = Model2.id
WHERE Model.id = 10;

こんなJOINは必要がないわけです。
JOINを回避する方法を調べたが、解決方法がよくわからず、unbindModel()や「$this->Model->recursive = -1」も試したが、JOINはされてしまうようです。
パフォーマンスを重視するなら、execute()を使ってもいいかと思います。
問題 => del()だと、必要ないテーブルがJOINされてしまう。


使い分けが上手くできればいいのかもしれないが、やっぱり気持ち悪いです。
1と2の解決策はあるのでしょうか?!

追記

1について。
execute()後に、findById()などで削除したデータがあるかどうかを調べれば、execute()が成功したのか?失敗したのか?わかるのではないかと思い、試してみた。

//削除するデータID
$id = 125;

//トランザクション
$this->UserUsingAccessory->begin(); echo "トランザクション<br />";

//executeする前
$sql = sprintf('SELECT id FROM user_using_accessories WHERE id = %d', $id);
$r = $this->UserUsingAccessory->query($sql);
echo 'executeする前にSELECTでデータを取得した結果 => ' . var_dump($r) . '<br />';

//executeパターン
$sql = sprintf('DELETE FROM user_using_accessories WHERE id = %d', $id);
$r = $this->UserUsingAccessory->query($sql);
echo 'executeの結果 => ' . var_dump($r) . '<br />';

//executeした後
$sql = sprintf('SELECT id FROM user_using_accessories WHERE id = %d', $id);
$r = $this->UserUsingAccessory->query($sql);
echo 'executeした後にSELECTでデータを取得した結果 => ' . var_dump($r) . '<br />';

//結果判定
if ($r) {
   $this->UserUsingAccessory->rollback(); echo "executeパターンでロールバック<br />";
   return;
}
//コミット
$this->UserUsingAccessory->commit();
echo "コミット<br />";
トランザクション

array
 0 => 
  array
   'user_using_accessories' => 
    array
     'id' => string '125' (length=3)

executeする前にSELECTでデータを取得した結果 =>

array
 empty

executeの結果 =>

array
 0 => 
  array
   'user_using_accessories' => 
    array
     'id' => string '125' (length=3)

executeした後にSELECTでデータを取得した結果 =>
executeパターンでロールバック

commit()をしなければデータの削除は行われないので、findByIdしすると普通にデータを取得できた。
DELETEしたのにデータがあるということは、成功したのか?失敗したのか?わからないので、結局execute()ではSQLの成功・失敗を取得することはできなかった。
残念だな。