Commit e3d57f0c by Qiang Xue

Merge branch 'console-color'

parents 0bdceee0 328bb2c0
......@@ -68,11 +68,10 @@ abstract class ActiveRecord extends Model
public static function model()
{
$className = get_called_class();
if (isset(self::$_models[$className])) {
return self::$_models[$className];
} else {
return self::$_models[$className] = new static;
if (!isset(self::$_models[$className])) {
self::$_models[$className] = new static;
}
return self::$_models[$className];
}
/**
......@@ -252,7 +251,7 @@ abstract class ActiveRecord extends Model
*/
public static function createActiveQuery()
{
return new ActiveQuery(get_called_class());
return new ActiveQuery(array('modelClass' => get_called_class()));
}
/**
......@@ -382,6 +381,38 @@ abstract class ActiveRecord extends Model
}
}
public function hasOne($class, $link)
{
return new HasOneRelation(array(
'modelClass' => $class,
'parentClass' => get_class($this),
'parentRecords' => array($this),
'link' => $link,
));
}
public function hasMany($class, $link)
{
return new HasManyRelation(array(
'modelClass' => $class,
'parentClass' => get_class($this),
'parentRecords' => array($this),
'link' => $link,
));
}
public function manyMany($class, $leftLink, $joinTable, $rightLink)
{
return new ManyManyRelation(array(
'modelClass' => $class,
'parentClass' => get_class($this),
'parentRecords' => array($this),
'leftLink' => $leftLink,
'joinTable' => $joinTable,
'rightLink' => $rightLink,
));
}
/**
* Initializes the internal storage for the relation.
* This method is internally used by [[ActiveQuery]] when populating relation data.
......
<?php
namespace yii\db\ar;
class HasManyRelation extends Relation
{
public $link;
}
<?php
namespace yii\db\ar;
class HasOneRelation extends Relation
{
public $link;
}
<?php
namespace yii\db\ar;
class ManyManyRelation extends Relation
{
public $joinTable;
public $leftLink;
public $rightLink;
}
<?php
namespace yii\db\ar;
class Relation extends ActiveQuery
{
public $parentClass;
public function findWith(&$parentRecords)
{
$this->andWhere(array('in', $links, $keys));
$records = $this->find();
foreach ($records as $record) {
// find the matching parent record(s)
// insert into the parent records(s)
}
}
}
......@@ -532,103 +532,23 @@ class BaseQuery extends \yii\base\Component
/**
* Merges this query with another one.
*
* The merging is done according to the following rules:
*
* - [[select]]: the union of both queries' [[select]] property values.
* - [[selectOption]], [[distinct]], [[from]], [[limit]], [[offset]]: the new query
* takes precedence over this query.
* - [[where]], [[having]]: the new query's corresponding property value
* will be 'AND' together with the existing one.
* - [[params]], [[orderBy]], [[groupBy]], [[join]], [[union]]: the new query's
* corresponding property value will be appended to the existing one.
*
* In general, the merging makes the resulting query more restrictive and specific.
* If a property of `$query` is not null, it will be used to overwrite
* the corresponding property of `$this`.
* @param BaseQuery $query the new query to be merged with this query.
* @return BaseQuery the query object itself
*/
public function mergeWith(BaseQuery $query)
{
if ($this->select !== $query->select) {
if (empty($this->select)) {
$this->select = $query->select;
} elseif (!empty($query->select)) {
$select1 = is_string($this->select) ? preg_split('/\s*,\s*/', trim($this->select), -1, PREG_SPLIT_NO_EMPTY) : $this->select;
$select2 = is_string($query->select) ? preg_split('/\s*,\s*/', trim($query->select), -1, PREG_SPLIT_NO_EMPTY) : $query->select;
$this->select = array_merge($select1, array_diff($select2, $select1));
}
}
if ($query->selectOption !== null) {
$this->selectOption = $query->selectOption;
}
if ($query->distinct !== null) {
$this->distinct = $query->distinct;
}
if ($query->from !== null) {
$this->from = $query->from;
}
if ($query->limit !== null) {
$this->limit = $query->limit;
}
if ($query->offset !== null) {
$this->offset = $query->offset;
}
if ($query->where !== null) {
$this->andWhere($query->where);
}
if ($query->having !== null) {
$this->andHaving($query->having);
}
if ($query->params !== null) {
$this->addParams($query->params);
}
if ($query->orderBy !== null) {
$this->addOrderBy($query->orderBy);
}
if ($query->groupBy !== null) {
$this->addGroup($query->groupBy);
}
if ($query->join !== null) {
if (empty($this->join)) {
$this->join = $query->join;
} else {
if (!is_array($this->join)) {
$this->join = array($this->join);
}
if (is_array($query->join)) {
$this->join = array_merge($this->join, $query->join);
} else {
$this->join[] = $query->join;
}
$properties = array(
'select', 'selectOption', 'distinct', 'from',
'where', 'limit', 'offset', 'orderBy', 'groupBy',
'join', 'having', 'union', 'params',
);
foreach ($properties as $name => $value) {
if ($value !== null) {
$this->$name = $value;
}
}
if ($query->union !== null) {
if (empty($this->union)) {
$this->union = $query->union;
} else {
if (!is_array($this->union)) {
$this->union = array($this->union);
}
if (is_array($query->union)) {
$this->union = array_merge($this->union, $query->union);
} else {
$this->union[] = $query->union;
}
}
}
return $this;
}
}
......@@ -469,16 +469,16 @@ class QueryBuilder extends \yii\base\Object
public function buildCondition($condition)
{
static $builders = array(
'and' => 'buildAndCondition',
'or' => 'buildAndCondition',
'between' => 'buildBetweenCondition',
'not between' => 'buildBetweenCondition',
'in' => 'buildInCondition',
'not in' => 'buildInCondition',
'like' => 'buildLikeCondition',
'not like' => 'buildLikeCondition',
'or like' => 'buildLikeCondition',
'or not like' => 'buildLikeCondition',
'AND' => 'buildAndCondition',
'OR' => 'buildAndCondition',
'BETWEEN' => 'buildBetweenCondition',
'NOT BETWEEN' => 'buildBetweenCondition',
'IN' => 'buildInCondition',
'NOT IN' => 'buildInCondition',
'LIKE' => 'buildLikeCondition',
'NOT LIKE' => 'buildLikeCondition',
'OR LIKE' => 'buildLikeCondition',
'OR NOT LIKE' => 'buildLikeCondition',
);
if (!is_array($condition)) {
......@@ -487,7 +487,7 @@ class QueryBuilder extends \yii\base\Object
return '';
}
if (isset($condition[0])) { // operator format: operator, operand 1, operand 2, ...
$operator = $condition[0];
$operator = strtoupper($condition[0]);
if (isset($builders[$operator])) {
$method = $builders[$operator];
array_shift($condition);
......@@ -534,7 +534,6 @@ class QueryBuilder extends \yii\base\Object
}
}
if ($parts !== array()) {
$operator = strtoupper($operator);
return '(' . implode(") $operator (", $parts) . ')';
} else {
return '';
......@@ -568,22 +567,62 @@ class QueryBuilder extends \yii\base\Object
$values = (array)$values;
if ($values === array()) {
if ($values === array() || $column === array()) {
return $operator === 'in' ? '0=1' : '';
}
if (is_array($column)) {
if (count($column) > 1) {
return $this->buildCompositeInCondition($operator, $column, $values);
} else {
$column = reset($column);
foreach ($values as $i => $value) {
if (is_array($value)) {
$values[$i] = isset($value[$column]) ? $value[$column] : null;
} else {
$values[$i] = null;
}
}
}
}
foreach ($values as $i => $value) {
$values[$i] = is_string($value) ? $this->connection->quoteValue($value) : (string)$value;
if ($value === null) {
$values[$i] = 'NULL';
} else {
$values[$i] = is_string($value) ? $this->connection->quoteValue($value) : (string)$value;
}
}
if (strpos($column, '(') === false) {
$column = $this->quoteColumnName($column);
}
$operator = strtoupper($operator);
return "$column $operator (" . implode(', ', $values) . ')';
}
protected function buildCompositeInCondition($operator, $columns, $values)
{
foreach ($columns as $i => $column) {
if (strpos($column, '(') === false) {
$columns[$i] = $this->quoteColumnName($column);
}
}
$vss = array();
foreach ($values as $value) {
$vs = array();
foreach ($columns as $column) {
if (isset($value[$column])) {
$vs[] = is_string($value[$column]) ? $this->connection->quoteValue($value[$column]) : (string)$value[$column];
} else {
$vs[] = 'NULL';
}
}
$vss[] = '(' . implode(', ', $vs) . ')';
}
return '(' . implode(', ', $columns) . ") $operator (" . implode(', ', $vss) . ')';
}
private function buildLikeCondition($operator, $operands)
{
if (!isset($operands[0], $operands[1])) {
......@@ -595,21 +634,20 @@ class QueryBuilder extends \yii\base\Object
$values = (array)$values;
if ($values === array()) {
return $operator === 'like' || $operator === 'or like' ? '0=1' : '';
return $operator === 'LIKE' || $operator === 'OR LIKE' ? '0=1' : '';
}
if ($operator === 'like' || $operator === 'not like') {
if ($operator === 'LIKE' || $operator === 'NOT LIKE') {
$andor = ' AND ';
} else {
$andor = ' OR ';
$operator = $operator === 'or like' ? 'like' : 'not like';
$operator = $operator === 'OR LIKE' ? 'LIKE' : 'NOT LIKE';
}
if (strpos($column, '(') === false) {
$column = $this->quoteColumnName($column);
}
$operator = strtoupper($operator);
$parts = array();
foreach ($values as $value) {
$parts[] = "$column $operator " . $this->connection->quoteValue($value);
......@@ -726,7 +764,7 @@ class QueryBuilder extends \yii\base\Object
$table = $driver->quoteTableName($table);
}
}
$joins[$i] = strtoupper($join[0]) . ' ' . $table;
$joins[$i] = $join[0] . ' ' . $table;
if (isset($join[2])) {
$condition = $this->buildCondition($join[2]);
if ($condition !== '') {
......
......@@ -23,42 +23,14 @@ class ActiveRecordTest extends \yiiunit\MysqlTestCase
$this->assertTrue($result instanceof ActiveQuery);
$customer = $result->one();
$this->assertTrue($customer instanceof Customer);
$this->assertEquals(1, $result->count);
$this->assertEquals(1, count($result));
// find all
$result = Customer::find();
$customers = $result->all();
$this->assertTrue(is_array($customers));
$this->assertEquals(3, count($customers));
$this->assertTrue($customers[0] instanceof Customer);
$this->assertTrue($customers[1] instanceof Customer);
$this->assertTrue($customers[2] instanceof Customer);
$this->assertEquals(3, $result->count);
$this->assertEquals(3, count($result));
// check count first
$result = Customer::find();
$this->assertEquals(3, $result->count);
$customer = $result->one();
$this->assertTrue($customer instanceof Customer);
$this->assertEquals(3, $result->count);
// iterator
$result = Customer::find();
$count = 0;
foreach ($result as $customer) {
$this->assertTrue($customer instanceof Customer);
$count++;
}
$this->assertEquals($count, $result->count);
// array access
$result = Customer::find();
$this->assertTrue($result[0] instanceof Customer);
$this->assertTrue($result[1] instanceof Customer);
$this->assertTrue($result[2] instanceof Customer);
$this->assertEquals(3, count($result));
// find by a single primary key
$customer = Customer::find(2);
......@@ -70,7 +42,7 @@ class ActiveRecordTest extends \yiiunit\MysqlTestCase
$this->assertTrue($customer instanceof Customer);
$this->assertEquals(2, $customer->id);
// find by Query
// find by Query array
$query = array(
'where' => 'id=:id',
'params' => array(':id' => 2),
......@@ -80,13 +52,59 @@ class ActiveRecordTest extends \yiiunit\MysqlTestCase
$this->assertEquals('user2', $customer->name);
// find count
$this->assertEquals(3, Customer::find()->count());
$this->assertEquals(3, Customer::count());
$this->assertEquals(2, Customer::count(array(
'where' => 'id=1 OR id=2',
)));
$this->assertEquals(2, Customer::count()->where('id=1 OR id=2'));
// $this->assertEquals(3, Customer::count());
// $this->assertEquals(2, Customer::count(array(
// 'where' => 'id=1 OR id=2',
// )));
// $this->assertEquals(2, Customer::find()->select('COUNT(*)')->where('id=1 OR id=2')->value());
}
public function testFindBySql()
{
// find one
$customer = Customer::findBySql('SELECT * FROM tbl_customer ORDER BY id DESC')->one();
$this->assertTrue($customer instanceof Customer);
$this->assertEquals('user3', $customer->name);
// find all
$customers = Customer::findBySql('SELECT * FROM tbl_customer')->all();
$this->assertEquals(3, count($customers));
// find with parameter binding
$customer = Customer::findBySql('SELECT * FROM tbl_customer WHERE id=:id', array(':id' => 2))->one();
$this->assertTrue($customer instanceof Customer);
$this->assertEquals('user2', $customer->name);
}
public function testScope()
{
$customers = Customer::find(array(
'scopes' => array('active'),
))->all();
$this->assertEquals(2, count($customers));
$customers = Customer::find()->active()->all();
$this->assertEquals(2, count($customers));
}
//
// public function testFindLazy()
// {
// $customer = Customer::find(2);
// $orders = $customer->orders;
// $this->assertEquals(2, count($orders));
//
// $orders = $customer->orders()->where('id=3')->all();
// $this->assertEquals(1, count($orders));
// $this->assertEquals(3, $orders[0]->id);
// }
//
// public function testFindEager()
// {
// $customers = Customer::find()->with('orders')->all();
// $this->assertEquals(3, count($customers));
// $this->assertEquals(1, count($customers[0]->orders));
// $this->assertEquals(2, count($customers[1]->orders));
// }
// public function testInsert()
// {
......
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