ZendFrameworkでfindAllBy{Field}メソッドを使う

RailsやCakePHPなどのフレームワークではお馴染みのfindBy系メソッドをZendFrameworkで実装したいということで。

Zend_Db_Tableクラスを継承したMyZend_Db_Tableクラス内のマジックメソッドで実装し、ModelはMyZend_Db_Tableを継承する。

<?php
class MyZend_Db_Table extends Zend_Db_Table {
    /**
     * 論理削除カラム名
     * @var string
     */
    private $_deleteCol = 'delete_time';

    /**
     * findAllBy[ColName]($value [, $flag])でデータアクセス
     *
     * $flag = true で論理削除された行は除外して取得
     *
     * @param string $method
     * @param array  $args
     * @return Zend_Db_Table_Row_Abstract
     */
    public function __call($method, $args) {
        if (preg_match('/^findAllBy(\w+)?$/', $method, $matches)) {
            $field = strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', $matches[1]));

            $where = array();
            $where["`$field` = ?"] = $args[0];

            if (isset($args[1]) && $args[1] === true
                && in_array($this->_deleteCol, $this->_cols)) {
                $where[] = "`{$this->_deleteCol}` IS NULL";
            }
            return $this->fetchAll($where);
        }
        throw new Zend_Db_Table_Exception("Call undefine method $method()");
    }
}

これで$model->findAllByName(‘Design’);のようにアクセスすれば`name` = ‘Design’という条件でのデータアクセスが可能になる。

データは論理削除する事が多いのでfindAllByName(‘Design’, true)の形の呼び出しで
`name` = ‘Design’ AND `delete_time` IS NULL

有効な行のみ返すようにしている。

まぁそんな感じで移植実装がおこなわれていくわけです。