読者です 読者をやめる 読者になる 読者になる

Zend_FrameworkのZend_DB_Select、これには順次処理でwhere文を生成する仕組みがあるのですが、単純な連結には便利でも複合条件の連結が使いにくくてタマラン、ということでhelperクラスを作ったのですよ。

Zend_DB_Selectのwhereメソッドの例

<?php
    $query = $tbl->select();
    $query->where('human=?', 1);
    $query->where('name like ?', 'イン%');
    
    :where文 (human=1) and (name like `イン%`)


    $query = $tbl->select();
    $query->where('human=?', 1);
    $query->where('(' . $db->quoteInto('name like ?', 'イン%') . ' or ' . $db->quoteInto('name like ?', 'イカ%') . ' or ' . $db->quoteInto('name = ?', 'キュアピース') . ')');
    
    :where文 (human=1) and ((name like `イン%`) or (name like `イカ%`) or (name = `キュアピース`))


ヘルパークラス(抜粋)。

<?php
class sqlHelper
{
    private $_whereArray = array();

    public function __construct()
    {
        $this->resetWhere();
    }

    /*
     * 順次処理でwhere文の条件式を連結
     * (条件を連結する処理のみ行う。条件のクオート処理は行わない)
     * ここでの連結は同じレベルでのみ行う。グループ化した条件とor/andをしたい場合は、事前にmakeWhereで条件を連結して、
     * 連結結果をaddOr/addAndで追加する。
     *
     * (ex.)
     *
     * (a=1) or (a=2) or (b=3) を生成 :
     *   resetWhere();
     *   addOr('a=1');
     *   addOr('a=2');
     *   addOr('b=3');
     *   結果 = makeWhere();
     *
     * ((a=1) or (a=2)) and (b=3) を生成 :
     *   resetWhere();
     *   addOr('a=1');
     *   addOr('a=2');
     *   s = makeWhere();
     *
     *   resetWhere();
     *   addOr(s);        // 注:リセット後の1回目はor/andどっちでも同じ
     *   addAnd('b=3');
     *   結果 = makeWhere();
     *
     */
    /**
     * where条件生成をリセット
     *
     */
    public function resetWhere()
    {
        $this->_whereArray = array();
    }

    /**
     * 指定した値をor条件として連結
     *
     * @param string $value
     */
    public function addOr($value)
    {
        $this->_whereArray[] = array('cond' => 'or', 'value' => $value);
    }

    /**
    * 指定した値をand条件として連結
    *
    * @param string $value
    */
    public function addAnd($value)
    {
        $this->_whereArray[] = array('cond' => 'and', 'value' => $value);
    }

    /**
     * addOr / addAndで作成した条件からwhere条件を生成
     *
     * @return string
     */
    public function makeWhere()
    {
        if (count($this->_whereArray) == 0) {
            return '';
        }

        $res = '';
        foreach ($this->_whereArray as $item) {
            if ($res == '') {
                $res = '(' . $item['value'] . ')';
            } else {
                $res = $res . ' ' . $item['cond'] . ' (' . $item['value'] . ')';
            }
        }
        return $res;
    }
}

で、こんな感じで連結。

<?php
    $query = $tbl->select();
    $query->where('human=?', 1);

    $sql = new sqlHelper;
    $sql->addOr($db->quoteInto('name like ?', 'イカ%'));
    $sql->addOr($db->quoteInto('name like ?', 'イン%'));
    $sql->addOr($db->quoteInto('name = ?', 'キュアピース'));
    $query->where($sql->makeWhere());
    
    :where文 (human=1) and ((name like `イカ%`) or (name like `イン%`) or (name = `キュアピース`))

‥‥、ただコレ、連結条件を生成した結果、条件が無かった場合には''を返すのですが、それをwhere()に突っ込むとご丁寧に''のまま条件を生成してくれてMySQLまで渡った後に例外になるのですよ。
makeWhereを使う毎に毎回毎回''チェックかけるのも面倒だし、where()にnullを渡したら無視してくれないかな?そうしたら戻り値をnullに変更するだけで簡単なのにとテストしたら‥‥、ご丁寧にnullのまま条件を生成してくれて(ry orz


事前チェックは出来ますが、毎度こんな判定するのは超面倒。

<?php
    if ($sql->makeWhere() <> '') {
        $query->where($sql->makeWhere());
    }