Wadslog

[Zend Framework] Zend_Db_Tableで、WHERE句をORで結合して行を取得する

Jan 15, 2008

Zned_Db_Table_Abstractを継承したクラスで、WHERE句を複数指定して行を取得する場合は以下のようにすると思います。$table = new Users(); $adapter = $table->getAdapter(); $where = array( $adapter->quoteInto('id = ?', $id'), $adapter->quoteInto('name = ?', $name) ); $rows = $table->fetchAll($where);この場合WHERE句はANDで結合されます(WHERE id = ‘…’ AND name = ‘…’ )。 今日ORで条件をつなげたいと思ったのですが、Zend_Db_Table_Abstractクラスにはそのようなものは用意されていませんでした。 普通に書くと以下のようになるかと思います。``` $where = $adapter->quoteInto(‘id = ?’, $id'); $where .= ' OR ' . $ adapter->quoteInto(‘name = ?’, $name'); $rows = $table->fetchAll($where); foreach($rows as $row) { // 各行に対する処理 }

// もしくは

$where = $adapter->quoteInto(‘id = ?’, $id'); $rows = $table->fetchAll($where); foreach($rows as $row) { if($row->name == $name) { // 各行に対する処理 } } fetchAllを追いかけてみると、最終的にZend\_Db\_Selectクラスのwhere()を呼び出していて、そこでwhere句をANDで結合して生成していました。 Zend\_Db\_Selectのソースをさらに読み進めるとorWhere()という関数があって、動作は想像のとおりwhere句をORで結合するものでした。この関数をうまく使えば、AND条件と同じようにプログラムを書けそうです。 Zend\_Db\_Table\_AbstractクラスのfetchAll()は内部で\_fetch()を呼び出し、さらに\_fetch()の内部でZend\_Db\_Selectクラスのwhere()を呼び出しています。このwhere()をorWhere()によびかえればうまくいきそうです。 うまく追加するには、Zend\_Db\_Table\_Abstractの関数を直接修正したり新しく関数を追加するのではなく、これを継承したクラスに以下の関数を追加して、さらにこれを継承してテーブルクラスを使うようにするのがいいと思います。 public function fetchAllOr($where = null, $order = null, $count = null, $offset = null) { $data = array( ‘table’ => $this, ‘data’ => $this->_fetchOr($where, $order, $count, $offset), ‘rowClass’ => $this->_rowClass, ‘stored’ => true );

Zend\_Loader::loadClass($this->\_rowsetClass);
return new $this->\_rowsetClass($data);

}

protected function _fetchOr($where = null, $order = null, $count = null, $offset = null) { // selection tool $select = $this->_db->select();

// the FROM clause
$select->from($this->\_name, $this->\_cols, $this->\_schema);

// the WHERE clause
$where = (array) $where;
foreach ($where as $key => $val) {
    // is $key an int?
    if (is\_int($key)) {
        // $val is the full condition
        $select->orWhere($val);
    } else {
        // $key is the condition with placeholder,
        // and $val is quoted into the condition
        $select->orWhere($key, $val);
    }
}

// the ORDER clause
if (!is\_array($order)) {
    $order = array($order);
}
foreach ($order as $val) {
    $select->order($val);
}

// the LIMIT clause
$select->limit($count, $offset);

// return the results
$stmt = $this->\_db->query($select);
$data = $stmt->fetchAll(Zend\_Db::FETCH\_ASSOC);
return $data;

} これまでのfetchAll同様に使えます(いつもながらネーミングが難しいですね)。 $table = new Users(); $adapter = $table->getAdapter(); $where = array( $adapter->quoteInto(‘id = ?’, $id'), $adapter->quoteInto(‘name = ?’, $name) ); $rows = $table->fetchAllOr($where);

comments powered by Disqus