Do You PHP はてブロ

Do You PHPはてなからはてブロに移動しました

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を使って実装されているようです。