Idea of Zend_Db_Select nested where clause
Zend Framework: 1.11.0
PHP: 5.3.3
なにしたかったの
せっかくだからと本家に入れてもらう用の記事書いたけれど
$adapter->quoteInto()を使う形が一番きれいな気がするw
nestedWhere()はquoteInto()のラップだけして登録はwhere()を使うのがいいのかな。
ということでボツ原稿を、がんばったんだぞっという記録で残しておきます。
片言の英語だって通じるんだ!きっと。
Description
I have an idea to make a SQL that has complex nested where clause.
This is a situation like
You have a web shop and user search ur products.
Ex)
SELECT * FROM table WHERE ( (permission = ?) AND (itemstatus = ?) ) AND ( (itemname LIKE '%abc%') AND ( (price < 1000) OR (quantity < 3) ) )
To make the SQL now. some way here.
// write SQL $sql = '((permission = ?) AND (itemstatus = ?)) AND (' . '(itemname LIKE ?) AND ((price < ?) OR (quantity < ?)))' $select->where($sql, $param); // combine where with some writing SQL $select->where('(permission = ?) AND (itemstatus = ?)', $param); $select->where('(itemname LIKE ?) AND ((price < ?) OR (quantity < ?))', $param); // manage where by array $nest1[] = $adapter->quoteInto('permission = ?', $param); $nest1[] = $adapter->quoteInto('itemstatus = ?', $param); $nest1 = implode(' AND ', $nest1); $nest2[] = $adapter->quoteInto('itemname LIKE ?', $param); $nest2_nest[] = $adapter->quoteInto('price < ?', $param); $nest2_nest[] = $adapter->quoteInto('quantity <?', $param); $nest2[] = implode(' OR ', $nest2_nest); $nest2 = implode(' AND ', $nest2); $select->where($nest1)->where($nest2);
How about adding new function like below code to Zend_Db_Select?
/* * Adds a WHERE clause to the query by AND * * clauses is same param of _where() * * <code> * $clauses[] = array('id = ?', $id, null, true); * $clauses[] = array('id = :id', null, null, false); * $select->where($clauses) * </code> * * @param array $clauses Array of WHERE condition set. * @param bool $bool OPTIONAL true = AND, false = OR. * * @see _where() */ public function whereNested($clauses, $bool = true) { if (count($this->_parts[self::UNION])) { require_once 'Zend/Db/Select/Exception.php'; throw new Zend_Db_Select_Exception("Invalid use of where clause with " . self::SQL_UNION); } $multi = false; foreach ($clauses as $clause) { if (count($clause) != 4) { require_once 'Zend/Db/Select/Exception.php'; throw new Zend_Db_Select_Exception("Invalid Where clauses '$clauses'"); } list($condition, $values, $type, $andor) = $clause; if ($values) { $condition = $this->_adapter->quoteInto($condition, $values, $type); } $cond = ''; if ($multi) { if ($andor === true) { $cond = self::SQL_AND . ' '; } else { $cond = self::SQL_OR . ' '; } } $parts[] = $cond . "($condition)"; $multi = true; } $condition = implode(' ', $parts); $cond = ''; if ($this->_parts[self::WHERE]) { if ($bool === true) { $cond = self::SQL_AND . ' '; } else { $cond = self::SQL_OR . ' '; } } $this->_parts[self::WHERE][] = $cond . "($condition)"; }
To use.
$select = $dbadapter->select(); $nest1[] = array('permission = ?', $permission, null, true); $nest1[] = array('itemstatus = ?', $itemstatus, null, true); $select->nestedWhere($nest1); $nest2[] = array('itemname LIKE ?', '%abc%', null, true); $nest2[] = $nest2[] = array('(price < ?) OR (quantity < ?), array(1000,3), true); $select->nestedWhere($nest2);
I think this code has some improved points.
Hate the line.
$nest2[] = array('(price < ?) OR (quantity < ?), array(1000,3), true);
But I don't know how to improve it.
I hope some ppl help this.