Symfony2でDoctrine2のFilterを使う
Doctrine2.2からSQLレベルで作用するFilterが使えるようになっています。このFilterでは強制的に「クエリ条件(WHERE句)」を追加することができ、Entityに定義した関連Entityの取得やDQLで発行されるSELECT文に対して追加されます。
で、論理削除を意味するカラム(delete_flag)の条件を追加するFilterのサンプルを書いてみました。
環境
- PHP5.4.6
- Symfony2.1.0-RC1 (7a233bc7a6f1a34150a358d223b12c76c1ed1674)
- Doctrine2.3.x-dev (971865f271771a3b06c474dfea9e91f023837cce)
Filterの作成
Filters - Object Relational Mapper (ORM) - Doctrineにあるとおり、Doctrine\ORM\Query\Filter\SQLFilter\SQLFilterクラスを継承し、抽象メソッドであるaddFilterConstraintメソッドを実装します。戻り値はクエリに追加するSQL文です。
<?php namespace Acme\DemoBundle\Entity\Filter; use Doctrine\ORM\Mapping\ClassMetaData; use Doctrine\ORM\Query\Filter\SQLFilter; class SoftDeleteFilter extends SQLFilter { public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias) { /** * ここは"生のSQL"として記述する(DQLではない) * 0=有効データ(削除データではない)、1=無効データ */ return "{$targetTableAlias}.delete_flag = '0' "; } }
Symfony2側に登録する
app.ymlにどう書けばいいのか?という部分ですが、ドキュメントが見当たらなかったのでDoctrine\Bundle\DoctrineBundle\DependencyInjection\Configurationクラスのソースを見てみましたが、以下のように書けば良いようです。
doctrine: dbal: : orm: auto_generate_proxy_classes: %kernel.debug% auto_mapping: true filters: softDeleteFilter: class: Acme\DemoBundle\Entity\Filter\SoftDeleteFilter enabled: true
発行されるSELECT文
実際にデータを取得しつつlogファイルを確認してみると、それぞれのSELECT文のWHERE句の最後に
SELECT ... AND ((t0.delete_flag = '0'))
という感じで条件が追加されていることが分かります。
まとめ
Filterも簡単に作成・登録できるようですね。テーブル設計に依存しますが、使う場面は意外と有りそうな感じがします。
なお、論理削除をサポートするBundleもあるようで、こちらもDoctrine2のFilterを使って実装されているようです。