Doctrineの論理削除


写真はドクペ。

Doctrineでfind使いたいんだけど論理削除があるからどうしてもできない!
ってことでgoogle:doctrine 論理削除でググッてみた。

アシアルブログですごくいいエントリーが沢山ヒット。

ただ少し古いのでアシアルブログのエントリを参考にDoctrineの公式サイトを直接見に行ったりして
Doctrine 1.2.4、Symfony1.4.10で動作するところまで調査できた。

DoctrineはデフォルトでSoftDeleteというモデルビヘイビアというものを持っている。
以下参照

ただし、ここで使用されるカラムのデフォルトの名称はdeleted_atである。
今回のプロジェクトで設計したテーブルは論理削除はすべてdel_flagという
名称であるため変更する必要がある。

変更対象となるクラスはDoctrine_Template_SoftDelete
これを継承してDelFlagという名称に変更する。
Doctrineのtemplateの置き場に迷ったがlib/model/doctrine/template
と新しく作成してその中に格納することにした。

mkdir %SF_LIB_DIR%/lib/model/doctrine/template
touch %SF_LIB_DIR%/lib/model/doctrine/template/DelFlag.class.php

プロパティのみの変更で動作するため$_optionsのnameのみ変えれば良い。

<?php
// lib/model/doctrine/template/DelFlag.class.php
class DelFlag extends Doctrine_Template_SoftDelete
{
    /**
     * Array of SoftDelete options
     *
     * @var string
     */
    protected $_options = array(
        'name'          =>  'del_flag',
        'type'          =>  'boolean',
        'length'        =>  null,
        'options'       =>  array(
            'notnull' => false
        ),
        'hardDelete' => false
    );
}
?>


一応新規で作成したディレクトリをautoload.ymlに登録する。

  # apps/%YOUR_APP_NAME%/config/autoload.yml
  model_template:
    name:           model template
    path:           %SF_LIB_DIR%/model/template
    recursive:      false


実際に利用するためにはschema.ymlに記載してbuildする必要がある。
ここでは仮にAccountというモデルに対して論理削除を設定するということにする。

  # config/doctrine/schema.yml
Account:
  columns:
  actAs:
    DelFlag: {}


以下のコマンドでモデルが生成される。

./symfony cc
./symfony doctrine:build --all --auto-load
<?php
    // lib/model/doctrine/base/BaseAccount.class.php
    public function setUp()
    {
        $delflag0 = new DelFlag(array(
             ));
        $this->actAs($delflag0);
    }

ProjectConfigurationにDoctrine用の記述をして完成。

<?php
    // config/ProjectConfiguration.class.php
    public function configureDoctrine($manager)
    {
        $manager->setAttribute(Doctrine::ATTR_USE_DQL_CALLBACKS, true);
    }

あとは動作チェック。
$account->delete();などと発行すると実際に行は残っており
論理削除のフラグ(del_flag)が1になったことを確認できる。

以上ちょっと便利だったのでブログにおこしました。