bakeするとview、edit、deleteするリンクを作ってくれる。でも、そのまま削除されると困ることもある。今回はactiveフラグを1から0に書き換えるように変更するにはどうしたらいいか考える。
◆bakeされたコード
◇viewの1レコードの終りに
<?php echo $html->link(__(‘Delete’, true), array(‘action’ => ‘delete’, $customer[‘Customer’][‘id’]), null, sprintf(__(‘Are you sure you want to delete # %s?’, true), $customer[‘Customer’][‘id’])); ?>
これをクリックすると実行するの?と聞かれ、Yesとすれば削除(=delete action)され、Noとすれば何も起こらない。
◇controllerのdelete actionは次のようになっている
function delete($id = null) {
if (!$id) {
$this->Session->setFlash(__(‘Invalid id for Customer’, true));
$this->redirect(array(‘action’=>’index’));
}
if ($this->Customer->del($id)) {
$this->Session->setFlash(__(‘Customer deleted’, true));
$this->redirect(array(‘action’=>’index’));
}
}
※これは1.2で作成された。たしか、1.3からはdelは非推奨になった気がする。
スポンサードリンク
◆既にあった!
んー。delにそのまま投げているのか。activeフラグを変更する場合はsaveを呼ばないといけないかな。
危ない危ない。車輪を~するところだった。調べてみると、もっと素晴らしいものがあった。softDeletableBehaviorというのがあるらしい。要するに論理削除してくれるもの。当に今やろうとしているそのもの。早速やってみる:
- Soft Deletable Behavior (Articles) | The Bakery, Everything CakePHP から soft_deletable.php をダウンロードする。執筆時1.1.38が最新らしい。
- 解凍して、/models/behaviors に入れる。
- 実行したいmodelに以下のコードを追加する
var $actsAs = array(‘SoftDeletable’); - ない場合はテーブルに以下を追加する
`deleted` TINYINT NOT NULL ;
`deleted_date` DATETIME NULL ;
◇削除したレコードを取得したいとき:
論理削除したレコードを含めて取得したい場合は find する前に下記のコードを実行します。
$this->Model->enableSoftDeletable(false);
論理削除を一時的に無効にすることができます。
◇素晴らしい点:
これだけで論理削除が実現できます。find などでも取得されなくなります。
SoftDeletable Behavior を使用すると Model::del は必ず false が返ります。これは Behavior が beforeDelete で削除フラグを立てて、モデルの del メソッドを実行させないために false を返すためです。この点だけ注意が必要です。
◆やってみる
やってみると、動作する。けれど、missing viewと言われる。しばらく悩む。renderを使わないようにするとか、viewを指定するとかやってみるも、ダメ。で、悩んだ挙句、”SoftDeletable Behavior を使用すると Model::del は必ず false が返ります”を思い出す。そうか。デフォルトのbakeコードは、idがあるかチェックして、あれば削除実行、成功すればtrueが返り、処理して完了。だから、falseが返った時の処理がない。だからautoRenderはdelete.ctpがないというのか。ということで、デフォルトのコードに!を追加して逆にしてあげればいいはず。
function delete($id = null) {
if (!$id) {
$this->Session->setFlash(__(‘Invalid id for Customer’, true));
$this->redirect(array(‘action’=>’index’));
}
if ($this->Customer->del($id)===false) {
$this->Session->setFlash(__(‘Customer deleted’, true));
$this->redirect(array(‘action’=>’index’));
}
}
ってことで期待通りに動作した。ふぅ。
”deleteしないでactiveフラグ変更する”をやろうとしたけれど、便利な論理削除が簡単に組み込めることがわかった。この実装をするとfindでも返らないということなので、findのwhereでactive=1とかしなくてもよくなるっぽい。それに、activeというカラムさえ不要になるんだろう。
参考文献
- “本当に削除せずに、削除フラグだけを立てるように挙動を変更(Soft Delete)” フォーラム – CakePHP Users in Japan :
CakePHP - Build fast, grow solid | PHPフレームワークCakePHP is an open-source web, rapid development framework that makes building web applications simpler, faster and requ... - [CakePHP] SoftDeletable Behavior で論理削除 | Sun Limited Mt. :
[CakePHP] SoftDeletable Behavior で論理削除 | Sun Limited Mt.先日の第4回 CakePHP 勉強会で発表した内容でもあるのですが、簡単に SoftDeletable Behavior
コメント