Commit cf10943c by Qiang Xue

...

parent 7f467291
......@@ -17,7 +17,8 @@ use yii\db\Exception;
/**
* ActiveFinder.php is ...
* todo: add SQL monitor
*
* todo: better handling on join() support in QueryBuilder: use regexp to detect table name and quote it
* todo: do not support anonymous parameter binding
* todo: add ActiveFinderBuilder
* todo: quote join/on part of the relational query
* todo: modify QueryBuilder about join() methods
......@@ -29,6 +30,7 @@ use yii\db\Exception;
* todo: lazy loading
* todo: scope
* todo: test via option
* todo: count, sum, exists
*
* @property integer $count
*
......@@ -80,6 +82,10 @@ class ActiveFinder extends \yii\base\Object implements \IteratorAggregate, \Arra
$this->query = new Query;
}
/**
* Executes query and returns all results as an array.
* @return array the query results. If the query results in nothing, an empty array will be returned.
*/
public function all()
{
if ($this->records === null) {
......@@ -89,15 +95,14 @@ class ActiveFinder extends \yii\base\Object implements \IteratorAggregate, \Arra
}
/**
* @param boolean $limitOne
* @return null|ActiveRecord
* Executes query and returns a single row of result.
* @return null|array|ActiveRecord the single row of query result. Depending on the setting of [[asArray]],
* the query result may be either an array or an ActiveRecord object. Null will be returned
* if the query results in nothing.
*/
public function one($limitOne = true)
public function one()
{
if ($this->records === null) {
if ($limitOne) {
$this->limit(1);
}
$this->records = $this->findRecords();
}
return isset($this->records[0]) ? $this->records[0] : null;
......@@ -442,96 +447,73 @@ class ActiveFinder extends \yii\base\Object implements \IteratorAggregate, \Arra
}
/**
* Appends an INNER JOIN part to the query.
* Appends a JOIN part to the query.
* The first parameter specifies what type of join it is.
* @param string $type the type of join, such as INNER JOIN, LEFT JOIN.
* @param string $table the table to be joined.
* Table name can contain schema prefix (e.g. 'public.tbl_user') and/or table alias (e.g. 'tbl_user u').
* The method will automatically quote the table name unless it contains some parenthesis
* (which means the table is given as a sub-query or DB expression).
* @param string|array $condition the join condition that should appear in the ON part.
* @param string|array $on the join condition that should appear in the ON part.
* Please refer to [[where()]] on how to specify this parameter.
* @param array $params the parameters (name=>value) to be bound to the query.
* Please refer to [[where()]] on alternative syntax of specifying anonymous parameters.
* @return ActiveFinder the query object itself
* @return Query the query object itself
*/
public function join($table, $condition, $params = array())
public function join($type, $table, $on = '', $params = array())
{
if (is_array($params)) {
$this->query->join($table, $condition, $params);
} else {
call_user_func_array(array($this->query, __FUNCTION__), func_get_args());
}
$this->query->join($type, $table, $on, $params);
return $this;
}
/**
* Appends a LEFT OUTER JOIN part to the query.
* Appends an INNER JOIN part to the query.
* @param string $table the table to be joined.
* Table name can contain schema prefix (e.g. 'public.tbl_user') and/or table alias (e.g. 'tbl_user u').
* The method will automatically quote the table name unless it contains some parenthesis
* (which means the table is given as a sub-query or DB expression).
* @param string|array $condition the join condition that should appear in the ON part.
* @param string|array $on the join condition that should appear in the ON part.
* Please refer to [[where()]] on how to specify this parameter.
* @param array $params the parameters (name=>value) to be bound to the query
* @param array $params the parameters (name=>value) to be bound to the query.
* Please refer to [[where()]] on alternative syntax of specifying anonymous parameters.
* @return ActiveFinder the query object itself
*/
public function leftJoin($table, $condition, $params = array())
public function innerJoin($table, $on, $params = array())
{
if (is_array($params)) {
$this->query->leftJoin($table, $condition, $params);
} else {
call_user_func_array(array($this->query, __FUNCTION__), func_get_args());
}
$this->query->join($table, $on, $params);
return $this;
}
/**
* Appends a RIGHT OUTER JOIN part to the query.
* Appends a LEFT OUTER JOIN part to the query.
* @param string $table the table to be joined.
* Table name can contain schema prefix (e.g. 'public.tbl_user') and/or table alias (e.g. 'tbl_user u').
* The method will automatically quote the table name unless it contains some parenthesis
* (which means the table is given as a sub-query or DB expression).
* @param string|array $condition the join condition that should appear in the ON part.
* @param string|array $on the join condition that should appear in the ON part.
* Please refer to [[where()]] on how to specify this parameter.
* @param array $params the parameters (name=>value) to be bound to the query
* @return ActiveFinder the query object itself
*/
public function rightJoin($table, $condition, $params = array())
{
if (is_array($params)) {
$this->query->rightJoin($table, $condition, $params);
} else {
call_user_func_array(array($this->query, __FUNCTION__), func_get_args());
}
return $this;
}
/**
* Appends a CROSS JOIN part to the query.
* Note that not all DBMS support CROSS JOIN.
* @param string $table the table to be joined.
* Table name can contain schema prefix (e.g. 'public.tbl_user') and/or table alias (e.g. 'tbl_user u').
* The method will automatically quote the table name unless it contains some parenthesis
* (which means the table is given as a sub-query or DB expression).
* @return ActiveFinder the query object itself
*/
public function crossJoin($table)
public function leftJoin($table, $on, $params = array())
{
$this->query->crossJoin($table);
$this->query->leftJoin($table, $on, $params);
return $this;
}
/**
* Appends a NATURAL JOIN part to the query.
* Note that not all DBMS support NATURAL JOIN.
* Appends a RIGHT OUTER JOIN part to the query.
* @param string $table the table to be joined.
* Table name can contain schema prefix (e.g. 'public.tbl_user') and/or table alias (e.g. 'tbl_user u').
* The method will automatically quote the table name unless it contains some parenthesis
* (which means the table is given as a sub-query or DB expression).
* @param string|array $on the join condition that should appear in the ON part.
* Please refer to [[where()]] on how to specify this parameter.
* @param array $params the parameters (name=>value) to be bound to the query
* @return ActiveFinder the query object itself
*/
public function naturalJoin($table)
public function rightJoin($table, $on, $params = array())
{
$this->query->naturalJoin($table);
$this->query->rightJoin($table, $on, $params);
return $this;
}
......@@ -746,7 +728,7 @@ class ActiveFinder extends \yii\base\Object implements \IteratorAggregate, \Arra
$rows = $command->queryAll();
if (!empty($this->with)) {
if (isset($joinTree)) {
foreach ($rows as $row) {
$joinTree->populateData($row);
}
......
......@@ -50,6 +50,17 @@ abstract class ActiveRecord extends Model
}
/**
* Returns the database connection used by this AR class.
* By default, the "db" application component is used as the database connection.
* You may override this method if you want to use a different database connection.
* @return Connection the database connection used by this AR class.
*/
public static function getDbConnection()
{
return \Yii::$application->getDb();
}
/**
* Creates an [[ActiveFinder]] instance for query purpose.
*
* Because [[ActiveFinder]] implements a set of query building methods,
......@@ -105,10 +116,6 @@ abstract class ActiveRecord extends Model
*/
public static function findBySql($sql, $params = array())
{
if (!is_array($params)) {
$params = func_get_args();
unset($params[0]);
}
$finder = static::createActiveFinder();
$finder->sql = $sql;
return $finder->params($params);
......@@ -155,17 +162,6 @@ abstract class ActiveRecord extends Model
}
/**
* Returns the database connection used by this AR class.
* By default, the "db" application component is used as the database connection.
* You may override this method if you want to use a different database connection.
* @return Connection the database connection used by this AR class.
*/
public static function getDbConnection()
{
return \Yii::$application->getDb();
}
/**
* Declares the name of the database table associated with this AR class.
* By default this method returns the class name as the table name by calling [[Text::camel2id()]].
* For example, 'Customer' becomes 'customer', and 'OrderDetail' becomes 'order_detail'.
......
......@@ -488,7 +488,7 @@ class QueryBuilder extends \yii\base\Object
);
if (!is_array($condition)) {
return $condition;
return (string)$condition;
} elseif ($condition === array()) {
return '';
}
......@@ -733,8 +733,11 @@ class QueryBuilder extends \yii\base\Object
}
}
$joins[$i] = strtoupper($join[0]) . ' ' . $table;
if (isset($join[2])) { // join condition
$joins[$i] .= ' ON ' . $this->buildCondition($join[2]);
if (isset($join[2])) {
$condition = $this->buildCondition($join[2]);
if ($condition !== '') {
$joins[$i] .= ' ON ' . $this->buildCondition($join[2]);
}
}
} else {
throw new Exception('A join clause must be specified as an array of at least two elements.');
......
......@@ -63,7 +63,8 @@ class ActiveRecordTest extends \yiiunit\MysqlTestCase
$pk = array('order_id' => 2, 'item_id' => 4);
$orderItem = OrderItem::find($pk)->one();
$this->assertEquals(1, $orderItem->quantity);
$orderItem->saveCounters(array('quantity' => -1));
$ret = $orderItem->saveCounters(array('quantity' => -1));
$this->assertTrue($ret);
$this->assertEquals(0, $orderItem->quantity);
$orderItem = OrderItem::find($pk)->one();
$this->assertEquals(0, $orderItem->quantity);
......@@ -71,9 +72,10 @@ class ActiveRecordTest extends \yiiunit\MysqlTestCase
// updateAll
$customer = Customer::find(3)->one();
$this->assertEquals('user3', $customer->name);
Customer::updateAll(array(
$ret = Customer::updateAll(array(
'name' => 'temp',
), array('id' => 3));
$this->assertEquals(1, $ret);
$customer = Customer::find(3)->one();
$this->assertEquals('temp', $customer->name);
......@@ -81,9 +83,10 @@ class ActiveRecordTest extends \yiiunit\MysqlTestCase
$pk = array('order_id' => 1, 'item_id' => 2);
$orderItem = OrderItem::find($pk)->one();
$this->assertEquals(2, $orderItem->quantity);
OrderItem::updateCounters(array(
$ret = OrderItem::updateCounters(array(
'quantity' => 3,
), $pk);
$this->assertEquals(1, $ret);
$orderItem = OrderItem::find($pk)->one();
$this->assertEquals(5, $orderItem->quantity);
}
......@@ -101,7 +104,8 @@ class ActiveRecordTest extends \yiiunit\MysqlTestCase
// deleteAll
$customers = Customer::find()->all();
$this->assertEquals(2, count($customers));
Customer::deleteAll();
$ret = Customer::deleteAll();
$this->assertEquals(2, $ret);
$customers = Customer::find()->all();
$this->assertEquals(0, count($customers));
}
......
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