* @link http://www.yiiframework.com/ * @copyright Copyright © 2008-2012 Yii Software LLC * @license http://www.yiiframework.com/license/ */ namespace yii\db\ar; use yii\db\dao\BaseQuery; use yii\base\VectorIterator; /** * ActiveFinder.php is ... * todo: add SQL monitor * * @author Qiang Xue * @since 2.0 */ class ActiveQuery extends BaseQuery implements \IteratorAggregate, \ArrayAccess, \Countable { public $modelClass; public $with; public $alias; public $indexBy; public $asArray; private $_count; private $_sql; private $_countSql; private $_records; public function all() { return $this->performQuery(); } public function one() { $this->limit = 1; $records = $this->performQuery(); if (isset($records[0])) { $this->_count = 1; return $records[0]; } else { $this->_count = 0; return null; } } public function asArray($value = true) { $this->asArray = $value; return $this; } public function with() { $this->with = func_get_args(); return $this; } public function indexBy($column) { $this->indexBy = $column; return $this; } public function alias($tableAlias) { $this->alias = $tableAlias; return $this; } protected function performQuery() { $class = $this->modelClass; $db = $class::getDbConnection(); $this->_sql = $this->getSql($db); $command = $db->createCommand($this->_sql); $command->bindValues($this->params); $rows = $command->queryAll(); if ($this->_asArray) { $records = $rows; } else { $records = array(); foreach ($rows as $row) { $records[] = $class::populateRecord($row); } } $this->_count = count($records); return $records; } // // public function getSql($connection = null) // { // // } public function setSql($value) { $this->_sql = $value; } public function getCountSql() { } public function getOneSql() { } /** * Returns the number of items in the vector. * @return integer the number of items in the vector */ public function getCount() { if ($this->_count !== null) { return $this->_count; } else { return $this->_count = $this->performCountQuery(); } } protected function performCountQuery() { $select = $this->select; $this->select = 'COUNT(*)'; $class = $this->modelClass; $command = $this->createCommand($class::getDbConnection()); $this->_countSql = $command->getSql(); $count = $command->queryScalar(); $this->select = $select; return $count; } /** * Sets the parameters about query caching. * This is a shortcut method to {@link CDbConnection::cache()}. * It changes the query caching parameter of the {@link dbConnection} instance. * @param integer $duration the number of seconds that query results may remain valid in cache. * If this is 0, the caching will be disabled. * @param CCacheDependency $dependency the dependency that will be used when saving the query results into cache. * @param integer $queryCount number of SQL queries that need to be cached after calling this method. Defaults to 1, * meaning that the next SQL query will be cached. * @return ActiveRecord the active record instance itself. */ public function cache($duration, $dependency = null, $queryCount = 1) { $this->connection->cache($duration, $dependency, $queryCount); return $this; } /** * Returns an iterator for traversing the items in the vector. * This method is required by the SPL interface `IteratorAggregate`. * It will be implicitly called when you use `foreach` to traverse the vector. * @return Iterator an iterator for traversing the items in the vector. */ public function getIterator() { $records = $this->performQuery(); return new VectorIterator($records); } /** * Returns the number of items in the vector. * This method is required by the SPL `Countable` interface. * It will be implicitly called when you use `count($vector)`. * @return integer number of items in the vector. */ public function count() { return $this->getCount(); } /** * Returns a value indicating whether there is an item at the specified offset. * This method is required by the SPL interface `ArrayAccess`. * It is implicitly called when you use something like `isset($vector[$offset])`. * @param integer $offset the offset to be checked * @return boolean whether there is an item at the specified offset. */ public function offsetExists($offset) { if ($this->_records === null) { $this->_records = $this->performQuery(); } return isset($this->_records[$offset]); } /** * Returns the item at the specified offset. * This method is required by the SPL interface `ArrayAccess`. * It is implicitly called when you use something like `$value = $vector[$offset];`. * This is equivalent to [[itemAt]]. * @param integer $offset the offset to retrieve item. * @return mixed the item at the offset * @throws Exception if the offset is out of range */ public function offsetGet($offset) { if ($this->_records === null) { $this->_records = $this->performQuery(); } return isset($this->_records[$offset]) ? $this->_records[$offset] : null; } /** * Sets the item at the specified offset. * This method is required by the SPL interface `ArrayAccess`. * It is implicitly called when you use something like `$vector[$offset] = $item;`. * If the offset is null or equal to the number of the existing items, * the new item will be appended to the vector. * Otherwise, the existing item at the offset will be replaced with the new item. * @param integer $offset the offset to set item * @param mixed $item the item value * @throws Exception if the offset is out of range, or the vector is read only. */ public function offsetSet($offset, $item) { if ($this->_records === null) { $this->_records = $this->performQuery(); } $this->_records[$offset] = $item; } /** * Unsets the item at the specified offset. * This method is required by the SPL interface `ArrayAccess`. * It is implicitly called when you use something like `unset($vector[$offset])`. * This is equivalent to [[removeAt]]. * @param integer $offset the offset to unset item * @throws Exception if the offset is out of range, or the vector is read only. */ public function offsetUnset($offset) { if ($this->_records === null) { $this->_records = $this->performQuery(); } unset($this->_records[$offset]); } }