Doctrineで論理削除を意識せずに扱う
こんにちは。小川です。
本日はDoctrineで論理削除を意識せずに扱う方法を紹介しようと思います。
結論から言うと、Doctrineが標準で用意しているSoftDeleteテンプレートをモデルに実装すれば自動的にクエリが発行する際に削除の判定を行ってくれるようになります。
テンプレートに関しては以前書いたブログがあるのでそちらを参考にしてください。
ただ上記の記事はDoctrine 0.11をベースに書いた記事なのですが、Doctrine 1.0からテンプレートの定義方法が少し変わったので先に少し説明します。
以前書いた記事では、config/doctrine/schema.ymlで
のようにtemplatesという名前で指定していましたが、templatesではなく「actAs」で指定するようになりました。
actAs自体は以前から存在しており、内容自体はほぼ同じです。
ちなみに以前書いたときはDoctrine_Template_Timestampableのように完全なクラス名を指定したのですが、クラスを生成する前にDoctrine_Template_で始まるクラスがあればそちらを使うような仕組みになっているためTimestampableと指定するだけでいいようです。
というわけで、論理削除をしたいモデルに対してschema.ymlで
上記のように記述すればSoftDeleteテンプレートが実装されます。
それではSoftDeleteテンプレートがどのようなことを行うのかを少し説明します。
SoftDeleteテンプレートを実装したモデルは自動的に
deletedカラムがモデルに追加され、trueの場合は削除として扱われるようになります。
検索時は、Doctrine_Queryのexecuteメソッドが実行されたタイミングで、(deleted = false OR deleted IS NULL)の条件が追加されます。もちろんエイリアスも張られます。
Doctrine_Tableに実装されているファインダメソッド(findXXX)や$article->getComments()などとやったときも内部でDoctrine_Queryが生成されるので
Doctrineのオブジェクトを取得する場合は大体大丈夫なのではないかと思います。
削除のときはDoctrine_QueryでDELETE文を発行する方法とRecordオブジェクトにdeleteメソッドを発行する方法が存在しますが、どちらの場合でもdeletedをtrueにUPDATEし、DELETEは行わないようになっています。
また、削除済みのものも検索で取得したい場合や物理削除を行いたい場合もあると思います。
これに関してはきれいな形での対応はされていないのですが、どちらもDoctrine_Queryでクエリを発行した場合にクエリにdeletedに関する記述がある場合はクエリを修正しないように作成されているため、
などの指定を追加してあげれば削除済みのレコードの検索や物理削除を行えます。
ただしこのときに
と書いた場合、クエリ中から"Article.deleted"を検索し記述がないものとして処理されるため、必ずエイリアスをつける必要があります。
ただしこれはSELECT限定で、DELETEのときはエイリアスがなくても動くようです。
ここまで実装方法などについて書いてきましたが、実はこれだけだと動きません。
Doctrineのデフォルトの設定では、Doctrine_Queryを実行前後で修正することが出来なくなっており、そこを設定してあげる必要があります。この設定の方法がsymfony 1.0とsymfony 1.1で変わってきます。
symfony 1.1ではProjectConfigurationクラスに設定を記述します。
上記のようにconfigureDoctrineメソッドでDoctrine::ATTR_USE_DQL_CALLBACKSをtrueにセットしなければいけません。
symfony 1.2でも同様です。というかsymfony 1.2でやったので上記がsymfony 1.1で動くかは実は検証してなかったりしますが、たぶん大丈夫だと思います。
symfony 1.0ではProjectConfigurationクラスはないのでどのようにやるかというと、sfDoctrinePlugin/configディレクトリの中にあるdoctrine.ymlをconfig直下にコピーしてきてそこに記述します。
attributes内にuse_dql_callbacksをtrueにする記述を追加すればOKです。ぶっちゃけこれも検証してないですがたぶん大丈夫だと思います。
SoftDeleteテンプレートについての説明は以上です。論理削除は全て自前で実装すると何かと面倒ですが、このテンプレートを使えばかなり楽になりそうですね。
Doctrineで論理削除を行う場合はぜひ使ってみてはいかがでしょうか。
本日はDoctrineで論理削除を意識せずに扱う方法を紹介しようと思います。
結論から言うと、Doctrineが標準で用意しているSoftDeleteテンプレートをモデルに実装すれば自動的にクエリが発行する際に削除の判定を行ってくれるようになります。
テンプレートに関しては以前書いたブログがあるのでそちらを参考にしてください。
ただ上記の記事はDoctrine 0.11をベースに書いた記事なのですが、Doctrine 1.0からテンプレートの定義方法が少し変わったので先に少し説明します。
以前書いた記事では、config/doctrine/schema.ymlで
- templates:
...
のようにtemplatesという名前で指定していましたが、templatesではなく「actAs」で指定するようになりました。
actAs自体は以前から存在しており、内容自体はほぼ同じです。
ちなみに以前書いたときはDoctrine_Template_Timestampableのように完全なクラス名を指定したのですが、クラスを生成する前にDoctrine_Template_で始まるクラスがあればそちらを使うような仕組みになっているためTimestampableと指定するだけでいいようです。
というわけで、論理削除をしたいモデルに対してschema.ymlで
- Article:
columns: ... actAs SoftDelete: {}
上記のように記述すればSoftDeleteテンプレートが実装されます。
それではSoftDeleteテンプレートがどのようなことを行うのかを少し説明します。
SoftDeleteテンプレートを実装したモデルは自動的に
deleted: { type: boolean, notnull: true, default: false }
deletedカラムがモデルに追加され、trueの場合は削除として扱われるようになります。
検索時は、Doctrine_Queryのexecuteメソッドが実行されたタイミングで、(deleted = false OR deleted IS NULL)の条件が追加されます。もちろんエイリアスも張られます。
Doctrine_Tableに実装されているファインダメソッド(findXXX)や$article->getComments()などとやったときも内部でDoctrine_Queryが生成されるので
Doctrineのオブジェクトを取得する場合は大体大丈夫なのではないかと思います。
削除のときはDoctrine_QueryでDELETE文を発行する方法とRecordオブジェクトにdeleteメソッドを発行する方法が存在しますが、どちらの場合でもdeletedをtrueにUPDATEし、DELETEは行わないようになっています。
また、削除済みのものも検索で取得したい場合や物理削除を行いたい場合もあると思います。
これに関してはきれいな形での対応はされていないのですが、どちらもDoctrine_Queryでクエリを発行した場合にクエリにdeletedに関する記述がある場合はクエリを修正しないように作成されているため、
- $query->addWhere("{$alias}.deleted
IS NOT NULL")
などの指定を追加してあげれば削除済みのレコードの検索や物理削除を行えます。
ただしこのときに
- Doctrine_Query::create()->from('Article')
->where('deleted IS NOT NULL')->execute(); - //
DQL => "FROM Article WHERE deleted IS NOT NULL"
と書いた場合、クエリ中から"Article.deleted"を検索し記述がないものとして処理されるため、必ずエイリアスをつける必要があります。
ただしこれはSELECT限定で、DELETEのときはエイリアスがなくても動くようです。
ここまで実装方法などについて書いてきましたが、実はこれだけだと動きません。
Doctrineのデフォルトの設定では、Doctrine_Queryを実行前後で修正することが出来なくなっており、そこを設定してあげる必要があります。この設定の方法がsymfony 1.0とsymfony 1.1で変わってきます。
symfony 1.1ではProjectConfigurationクラスに設定を記述します。
- class
ProjectConfiguration extends sfProjectConfiguration - {
protected $plugins = array('sfDoctrinePlugin'); public function configureDoctrine($manager) { $manager->setAttribute(Doctrine::ATTR_USE_DQL_CALLBACKS, true); } - }
上記のようにconfigureDoctrineメソッドでDoctrine::ATTR_USE_DQL_CALLBACKSをtrueにセットしなければいけません。
symfony 1.2でも同様です。というかsymfony 1.2でやったので上記がsymfony 1.1で動くかは実は検証してなかったりしますが、たぶん大丈夫だと思います。
symfony 1.0ではProjectConfigurationクラスはないのでどのようにやるかというと、sfDoctrinePlugin/configディレクトリの中にあるdoctrine.ymlをconfig直下にコピーしてきてそこに記述します。
- all:
attributes: use_dql_callbacks: true
attributes内にuse_dql_callbacksをtrueにする記述を追加すればOKです。ぶっちゃけこれも検証してないですがたぶん大丈夫だと思います。
SoftDeleteテンプレートについての説明は以上です。論理削除は全て自前で実装すると何かと面倒ですが、このテンプレートを使えばかなり楽になりそうですね。
Doctrineで論理削除を行う場合はぜひ使ってみてはいかがでしょうか。
コメントフォーム
トラックバック
最近の記事
- もうすぐ健康診断があるんだ・・・ [2010年09月02日 : 阿部恵]
- Photoshopで壁紙を作りながら、基本的な使い方を覚える [2010年09月01日 : 鴨田健次]
- はじめての共同作業 Canvas編 (node.js + websocket) [2010年09月01日 : 中川善樹]
- 「PHP×Flex(後編)」PHPテクニカルセミナー(無料)第4弾の募集を開始しました!! [2010年08月26日 : 和田記光]
- 【HTML5】Canvasでお絵かきしてみた(前編) [2010年08月25日 : 橋本章史]
- MacにgroongaのMySQL用ストレージエンジン [2010年08月23日 : 笹亀弘]
- Appleのサイトで見たiPhone4をFireworksで描いてみました-1/2 [2010年08月19日 : 和田記光]
- iPad版の会社紹介を作ってみました [2010年08月19日 : 小林有佳]
- iPhoneアプリ開発開始時に気をつけるべきファイルの取り扱い (2) [2010年08月19日 : 亀本大地]
- symfonyセミナー動画無料公開! [2010年08月13日 : 岡本雄樹]



最近のコメント