Commit e5534b3c by Alexander Makarov

Merge remote-tracking branch 'origin/master'

parents 6f964b6d f62d0622
......@@ -76,16 +76,16 @@ class YiiBase
/**
* @var array initial property values that will be applied to objects newly created via [[createObject]].
* The array keys are fully qualified namespaced class names, and the array values are the corresponding
* name-value pairs for initializing the created class instances. Make sure the class names do NOT have
* the leading backslashes. For example,
* name-value pairs for initializing the created class instances. Please make sure class names are starting
* with a backslash. For example,
*
* ~~~
* array(
* 'mycompany\foo\Bar' => array(
* '\Bar' => array(
* 'prop1' => 'value1',
* 'prop2' => 'value2',
* ),
* 'mycompany\foo\Car' => array(
* '\mycompany\foo\Car' => array(
* 'prop1' => 'value1',
* 'prop2' => 'value2',
* ),
......@@ -301,6 +301,9 @@ class YiiBase
/**
* Creates a new object using the given configuration.
*
* The class of the object can be any class. It does not have to
* extend from [[Object]] or [[Component]].
*
* The configuration can be either a string or an array.
* If a string, it is treated as the *object type*; if an array,
* it must contain a `class` element specifying the *object type*, and
......@@ -310,7 +313,7 @@ class YiiBase
* The object type can be either a class name or the [[getAlias|alias]] of
* the class. For example,
*
* - `\app\components\GoogleMap`: namespaced class
* - `\app\components\GoogleMap`: full qualified namespaced class.
* - `@app/components/GoogleMap`: an alias
*
* This method does the following steps to create an object:
......@@ -319,7 +322,7 @@ class YiiBase
* - if [[objectConfig]] contains the configuration for the object class,
* it will be merged with the configuration passed to this method;
* - initialize the object properties using the configuration passed to this method;
* - call the `init` method of the object if it implements the [[yii\base\Initable]] interface.
* - call the `init` method of the object if it implements the [[\yii\base\Initable]] interface.
*
* Below are some usage examples:
*
......@@ -337,6 +340,7 @@ class YiiBase
* @param mixed $config the configuration. It can be either a string or an array.
* @return mixed the created object
* @throws \yii\base\Exception if the configuration is invalid.
* @see \yii\base\Object::newInstance()
*/
public static function createObject($config)
{
......@@ -372,9 +376,9 @@ class YiiBase
$object = $r->newInstanceArgs($args);
}
$c = get_class($object);
if (isset(\Yii::$objectConfig[$c])) {
$config = array_merge(\Yii::$objectConfig[$c], $config);
$class = '\\' . get_class($object);
if (isset(\Yii::$objectConfig[$class])) {
$config = array_merge(\Yii::$objectConfig[$class], $config);
}
foreach ($config as $name => $value) {
......
......@@ -461,11 +461,8 @@ class Component extends Object
*/
public function attachBehavior($name, $behavior)
{
if (!($behavior instanceof Behavior)) {
$behavior = \Yii::createObject($behavior);
}
$behavior->attach($this);
return $this->_b[$name] = $behavior;
$this->ensureBehaviors();
return $this->attachBehaviorInternal($name, $behavior);
}
/**
......@@ -478,8 +475,9 @@ class Component extends Object
*/
public function attachBehaviors($behaviors)
{
$this->ensureBehaviors();
foreach ($behaviors as $name => $behavior) {
$this->attachBehavior($name, $behavior);
$this->attachBehaviorInternal($name, $behavior);
}
}
......@@ -523,8 +521,23 @@ class Component extends Object
if ($this->_b === null) {
$this->_b = array();
foreach ($this->behaviors() as $name => $behavior) {
$this->attachBehavior($name, $behavior);
$this->attachBehaviorInternal($name, $behavior);
}
}
}
/**
* Attaches a behavior to this component.
* @param string $name the name of the behavior.
* @param string|array|Behavior $behavior the behavior to be attached
* @return Behavior the attached behavior.
*/
private function attachBehaviorInternal($name, $behavior)
{
if (!($behavior instanceof Behavior)) {
$behavior = \Yii::createObject($behavior);
}
$behavior->attach($this);
return $this->_b[$name] = $behavior;
}
}
......@@ -300,8 +300,7 @@ class Object
*/
public static function newInstance($config = array())
{
$c = get_called_class();
$class = '\\' . $c;
$class = '\\' . get_called_class();
if (($n = func_num_args()-1) > 0) {
$args = func_get_args();
......@@ -321,8 +320,8 @@ class Object
$object = $r->newInstanceArgs($args);
}
if (isset(\Yii::$objectConfig[$c])) {
$config = array_merge(\Yii::$objectConfig[$c], $config);
if (isset(\Yii::$objectConfig[$class])) {
$config = array_merge(\Yii::$objectConfig[$class], $config);
}
foreach ($config as $name => $value) {
......
......@@ -10,6 +10,9 @@
namespace yii\db\ar;
use yii\db\dao\BaseQuery;
use yii\base\VectorIterator;
/**
* ActiveFinder.php is ...
* todo: add SQL monitor
......@@ -17,86 +20,72 @@ namespace yii\db\ar;
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class ActiveQuery extends \yii\db\dao\BaseQuery implements \IteratorAggregate, \ArrayAccess, \Countable
class ActiveQuery extends BaseQuery implements \IteratorAggregate, \ArrayAccess, \Countable
{
public $modelClass;
public $with;
public $alias;
public $index;
public $indexBy;
public $asArray;
private $_count;
private $_sql;
private $_countSql;
private $_asArray;
private $_records;
public $records;
public $sql;
public function all()
public function all($refresh = false)
{
return $this->performQuery();
if ($this->records === null || $refresh) {
$this->records = $this->performQuery();
}
return $this->records;
}
public function one()
public function one($refresh = false)
{
$this->limit = 1;
$records = $this->performQuery();
if (isset($records[0])) {
$this->_count = 1;
return $records[0];
if ($this->records === null || $refresh) {
$this->limit = 1;
$this->records = $this->performQuery();
}
if (isset($this->records[0])) {
return $this->records[0];
} else {
$this->_count = 0;
return null;
}
}
public function asArray($value = true)
{
$this->_asArray = $value;
}
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;
$this->asArray = $value;
return $this;
}
public function with()
{
$this->with = func_get_args();
return $this;
}
//
// public function getSql($connection = null)
// {
//
// }
public function setSql($value)
public function indexBy($column)
{
$this->_sql = $value;
$this->indexBy = $column;
return $this;
}
public function getCountSql()
public function alias($tableAlias)
{
$this->alias = $tableAlias;
return $this;
}
public function getOneSql()
/**
* Returns the database connection used by this query.
* This method returns the connection used by the [[modelClass]].
* @return \yii\db\dao\Connection the database connection used by this query
*/
public function getDbConnection()
{
$class = $this->modelClass;
return $class::getDbConnection();
}
/**
......@@ -105,23 +94,7 @@ class ActiveQuery extends \yii\db\dao\BaseQuery implements \IteratorAggregate, \
*/
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;
return $this->count();
}
/**
......@@ -137,7 +110,7 @@ class ActiveQuery extends \yii\db\dao\BaseQuery implements \IteratorAggregate, \
*/
public function cache($duration, $dependency = null, $queryCount = 1)
{
$this->connection->cache($duration, $dependency, $queryCount);
$this->getDbConnection()->cache($duration, $dependency, $queryCount);
return $this;
}
......@@ -149,19 +122,30 @@ class ActiveQuery extends \yii\db\dao\BaseQuery implements \IteratorAggregate, \
*/
public function getIterator()
{
$records = $this->performQuery();
return new \yii\base\VectorIterator($records);
if ($this->records === null) {
$this->records = $this->performQuery();
}
return new VectorIterator($this->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)`.
* @param boolean $bySql whether to get the count by performing a SQL COUNT query.
* If this is false, it will count the number of records brought back by this query.
* @return integer number of items in the vector.
*/
public function count()
public function count($bySql = false)
{
return $this->getCount();
if ($bySql) {
return $this->performCountQuery();
} else {
if ($this->records === null) {
$this->records = $this->performQuery();
}
return count($this->records);
}
}
/**
......@@ -173,10 +157,10 @@ class ActiveQuery extends \yii\db\dao\BaseQuery implements \IteratorAggregate, \
*/
public function offsetExists($offset)
{
if ($this->_records === null) {
$this->_records = $this->performQuery();
if ($this->records === null) {
$this->records = $this->performQuery();
}
return isset($this->_records[$offset]);
return isset($this->records[$offset]);
}
/**
......@@ -190,10 +174,10 @@ class ActiveQuery extends \yii\db\dao\BaseQuery implements \IteratorAggregate, \
*/
public function offsetGet($offset)
{
if ($this->_records === null) {
$this->_records = $this->performQuery();
if ($this->records === null) {
$this->records = $this->performQuery();
}
return isset($this->_records[$offset]) ? $this->_records[$offset] : null;
return isset($this->records[$offset]) ? $this->records[$offset] : null;
}
/**
......@@ -209,10 +193,10 @@ class ActiveQuery extends \yii\db\dao\BaseQuery implements \IteratorAggregate, \
*/
public function offsetSet($offset, $item)
{
if ($this->_records === null) {
$this->_records = $this->performQuery();
if ($this->records === null) {
$this->records = $this->performQuery();
}
$this->_records[$offset] = $item;
$this->records[$offset] = $item;
}
/**
......@@ -225,9 +209,38 @@ class ActiveQuery extends \yii\db\dao\BaseQuery implements \IteratorAggregate, \
*/
public function offsetUnset($offset)
{
if ($this->_records === null) {
$this->_records = $this->performQuery();
if ($this->records === null) {
$this->records = $this->performQuery();
}
unset($this->records[$offset]);
}
protected function performQuery()
{
$db = $this->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();
$class = $this->modelClass;
foreach ($rows as $row) {
$records[] = $class::populateData($row);
}
}
unset($this->_records[$offset]);
return $records;
}
protected function performCountQuery()
{
$this->select = 'COUNT(*)';
$class = $this->modelClass;
$command = $this->createCommand($class::getDbConnection());
$this->sql = $command->getSql();
$count = $command->queryScalar();
return $count;
}
}
......@@ -308,7 +308,7 @@ abstract class ActiveRecord extends \yii\base\Model
*/
public function __construct($scenario = 'insert')
{
if ($scenario === null) // internally used by populateRecord() and model()
if ($scenario === null) // internally used by populateData() and model()
{
return;
}
......@@ -1186,7 +1186,7 @@ abstract class ActiveRecord extends \yii\base\Model
* @return ActiveRecord the newly created active record. The class of the object is the same as the model class.
* Null is returned if the input data is false.
*/
public static function populateRecord($row)
public static function populateData($row)
{
$record = static::instantiate($row);
$record->setScenario('update');
......@@ -1204,7 +1204,7 @@ abstract class ActiveRecord extends \yii\base\Model
/**
* Creates an active record instance.
* This method is called by {@link populateRecord} and {@link populateRecords}.
* This method is called by {@link populateData}.
* You may override this method if the instance being created
* depends the attributes that are to be populated to the record.
* For example, by creating a record based on the value of a column,
......
......@@ -43,7 +43,7 @@ class Query extends BaseQuery
{
/**
* @var array the operation that this query represents. This refers to the method call as well as
* the corresponding parameters for constructing a non-query SQL statement (e.g. INSERT, CREATE TABLE).
* the corresponding parameters for constructing a non-select SQL statement (e.g. INSERT, CREATE TABLE).
* This property is mainly maintained by methods such as [[insert()]], [[update()]], [[createTable()]].
* If this property is not set, it means this query represents a SELECT statement.
*/
......
......@@ -31,6 +31,9 @@ Upgrading from v1.1.x
- The root alias `@yii` now represents the framework installation directory.
In 1.x, this is named as `system`. We also removed `zii` root alias.
- Object serves as the base class that supports properties. And Component extends
from Object and supports events and behaviors. Behaviors declared in
Component::behaviors() are attached on demand.
- `CList` is renamed to `Vector`, and `CMap` is renamed to `Dictionary`.
Other collection classes are dropped in favor of SPL classes.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment