Browse Source

Merge pull request #13210 from yiisoft/query-filter-having

Query filter having
tags/2.0.11
Alexander Makarov 8 years ago committed by GitHub
parent
commit
cc23f94b5d
  1. 6
      docs/guide/db-query-builder.md
  2. 1
      framework/CHANGELOG.md
  3. 95
      framework/db/Query.php
  4. 65
      tests/framework/db/QueryTest.php

6
docs/guide/db-query-builder.md

@ -369,6 +369,12 @@ You can also specify operator explicitly:
$query->andFilterCompare('name', 'Doe', 'like');
```
Since Yii 2.0.11 there are similar methods for `HAVING` condition:
- [[yii\db\Query::filterHaving()|filterHaving()]]
- [[yii\db\Query::andFilterHaving()|andFilterHaving()]]
- [[yii\db\Query::orFilterHaving()|orFilterHaving()]]
### [[yii\db\Query::orderBy()|orderBy()]] <span id="order-by"></span>
The [[yii\db\Query::orderBy()|orderBy()]] method specifies the `ORDER BY` fragment of a SQL query. For example,

1
framework/CHANGELOG.md

@ -74,6 +74,7 @@ Yii Framework 2 Change Log
- Enh: Added constants for specifying `yii\validators\CompareValidator::$type` (cebe)
- Enh #12854: Added `RangeNotSatisfiableHttpException` to cover HTTP error 416 file request exceptions (zalatov)
- Enh #13122: Optimized query for information about foreign keys in `yii\db\oci` (zlakomanoff)
- Enh #11697: Added `filterHaving()`, `andFilterHaving()` and `orFilterHaving()` to `yii\db\Query` (nicdnepr, samdark)
- Enh #13202: Refactor validateAttribute method in UniqueValidator (developeruz)
2.0.10 October 20, 2016

95
framework/db/Query.php

@ -573,7 +573,7 @@ class Query extends Component implements QueryInterface
/**
* Adds an additional WHERE condition to the existing one.
* The new condition and the existing one will be joined using the 'AND' operator.
* The new condition and the existing one will be joined using the `AND` operator.
* @param string|array|Expression $condition the new WHERE condition. Please refer to [[where()]]
* on how to specify this parameter.
* @param array $params the parameters (name => value) to be bound to the query.
@ -594,7 +594,7 @@ class Query extends Component implements QueryInterface
/**
* Adds an additional WHERE condition to the existing one.
* The new condition and the existing one will be joined using the 'OR' operator.
* The new condition and the existing one will be joined using the `OR` operator.
* @param string|array|Expression $condition the new WHERE condition. Please refer to [[where()]]
* on how to specify this parameter.
* @param array $params the parameters (name => value) to be bound to the query.
@ -619,7 +619,7 @@ class Query extends Component implements QueryInterface
* It adds an additional WHERE condition for the given field and determines the comparison operator
* based on the first few characters of the given value.
* The condition is added in the same way as in [[andFilterWhere]] so [[isEmpty()|empty values]] are ignored.
* The new condition and the existing one will be joined using the 'AND' operator.
* The new condition and the existing one will be joined using the `AND` operator.
*
* The comparison operator is intelligently determined based on the first few characters in the given value.
* In particular, it recognizes the following operators if they appear as the leading characters in the given value:
@ -832,7 +832,7 @@ class Query extends Component implements QueryInterface
/**
* Adds an additional HAVING condition to the existing one.
* The new condition and the existing one will be joined using the 'AND' operator.
* The new condition and the existing one will be joined using the `AND` operator.
* @param string|array|Expression $condition the new HAVING condition. Please refer to [[where()]]
* on how to specify this parameter.
* @param array $params the parameters (name => value) to be bound to the query.
@ -853,7 +853,7 @@ class Query extends Component implements QueryInterface
/**
* Adds an additional HAVING condition to the existing one.
* The new condition and the existing one will be joined using the 'OR' operator.
* The new condition and the existing one will be joined using the `OR` operator.
* @param string|array|Expression $condition the new HAVING condition. Please refer to [[where()]]
* on how to specify this parameter.
* @param array $params the parameters (name => value) to be bound to the query.
@ -873,6 +873,91 @@ class Query extends Component implements QueryInterface
}
/**
* Sets the HAVING part of the query but ignores [[isEmpty()|empty operands]].
*
* This method is similar to [[having()]]. The main difference is that this method will
* remove [[isEmpty()|empty query operands]]. As a result, this method is best suited
* for building query conditions based on filter values entered by users.
*
* The following code shows the difference between this method and [[having()]]:
*
* ```php
* // HAVING `age`=:age
* $query->filterHaving(['name' => null, 'age' => 20]);
* // HAVING `age`=:age
* $query->having(['age' => 20]);
* // HAVING `name` IS NULL AND `age`=:age
* $query->having(['name' => null, 'age' => 20]);
* ```
*
* Note that unlike [[having()]], you cannot pass binding parameters to this method.
*
* @param array $condition the conditions that should be put in the HAVING part.
* See [[having()]] on how to specify this parameter.
* @return $this the query object itself
* @see having()
* @see andFilterHaving()
* @see orFilterHaving()
* @since 2.0.11
*/
public function filterHaving(array $condition)
{
$condition = $this->filterCondition($condition);
if ($condition !== []) {
$this->having($condition);
}
return $this;
}
/**
* Adds an additional HAVING condition to the existing one but ignores [[isEmpty()|empty operands]].
* The new condition and the existing one will be joined using the `AND` operator.
*
* This method is similar to [[andHaving()]]. The main difference is that this method will
* remove [[isEmpty()|empty query operands]]. As a result, this method is best suited
* for building query conditions based on filter values entered by users.
*
* @param array $condition the new HAVING condition. Please refer to [[having()]]
* on how to specify this parameter.
* @return $this the query object itself
* @see filterHaving()
* @see orFilterHaving()
* @since 2.0.11
*/
public function andFilterHaving(array $condition)
{
$condition = $this->filterCondition($condition);
if ($condition !== []) {
$this->andHaving($condition);
}
return $this;
}
/**
* Adds an additional HAVING condition to the existing one but ignores [[isEmpty()|empty operands]].
* The new condition and the existing one will be joined using the `OR` operator.
*
* This method is similar to [[orHaving()]]. The main difference is that this method will
* remove [[isEmpty()|empty query operands]]. As a result, this method is best suited
* for building query conditions based on filter values entered by users.
*
* @param array $condition the new HAVING condition. Please refer to [[having()]]
* on how to specify this parameter.
* @return $this the query object itself
* @see filterHaving()
* @see andFilterHaving()
* @since 2.0.11
*/
public function orFilterHaving(array $condition)
{
$condition = $this->filterCondition($condition);
if ($condition !== []) {
$this->orHaving($condition);
}
return $this;
}
/**
* Appends a SQL statement using UNION operator.
* @param string|Query $sql the SQL statement to be appended using UNION
* @param bool $all TRUE if using UNION ALL and FALSE if using UNION

65
tests/framework/db/QueryTest.php

@ -56,9 +56,8 @@ abstract class QueryTest extends DatabaseTestCase
$this->assertEquals([':id' => 1, ':name' => 'something', ':age' => '30'], $query->params);
}
public function testFilterWhere()
public function testFilterWhereWithHashFormat()
{
// should work with hash format
$query = new Query;
$query->filterWhere([
'id' => 0,
@ -72,8 +71,10 @@ abstract class QueryTest extends DatabaseTestCase
$query->orFilterWhere(['name' => '']);
$this->assertEquals(['id' => 0], $query->where);
}
// should work with operator format
public function testFilterWhereWithOperatorFormat()
{
$query = new Query;
$condition = ['like', 'name', 'Alex'];
$query->filterWhere($condition);
@ -91,9 +92,6 @@ abstract class QueryTest extends DatabaseTestCase
$query->andFilterWhere(['not in', 'id', []]);
$this->assertEquals($condition, $query->where);
$query->andFilterWhere(['not in', 'id', []]);
$this->assertEquals($condition, $query->where);
$query->andFilterWhere(['like', 'id', '']);
$this->assertEquals($condition, $query->where);
@ -110,6 +108,58 @@ abstract class QueryTest extends DatabaseTestCase
$this->assertEquals($condition, $query->where);
}
public function testFilterHavingWithHashFormat()
{
$query = new Query;
$query->filterHaving([
'id' => 0,
'title' => ' ',
'author_ids' => [],
]);
$this->assertEquals(['id' => 0], $query->having);
$query->andFilterHaving(['status' => null]);
$this->assertEquals(['id' => 0], $query->having);
$query->orFilterHaving(['name' => '']);
$this->assertEquals(['id' => 0], $query->having);
}
public function testFilterHavingWithOperatorFormat()
{
$query = new Query;
$condition = ['like', 'name', 'Alex'];
$query->filterHaving($condition);
$this->assertEquals($condition, $query->having);
$query->andFilterHaving(['between', 'id', null, null]);
$this->assertEquals($condition, $query->having);
$query->orFilterHaving(['not between', 'id', null, null]);
$this->assertEquals($condition, $query->having);
$query->andFilterHaving(['in', 'id', []]);
$this->assertEquals($condition, $query->having);
$query->andFilterHaving(['not in', 'id', []]);
$this->assertEquals($condition, $query->having);
$query->andFilterHaving(['like', 'id', '']);
$this->assertEquals($condition, $query->having);
$query->andFilterHaving(['or like', 'id', '']);
$this->assertEquals($condition, $query->having);
$query->andFilterHaving(['not like', 'id', ' ']);
$this->assertEquals($condition, $query->having);
$query->andFilterHaving(['or not like', 'id', null]);
$this->assertEquals($condition, $query->having);
$query->andFilterHaving(['or', ['eq', 'id', null], ['eq', 'id', []]]);
$this->assertEquals($condition, $query->having);
}
public function testFilterRecursively()
{
$query = new Query();
@ -272,7 +322,8 @@ abstract class QueryTest extends DatabaseTestCase
}
/**
* @depends testFilterWhere
* @depends testFilterWhereWithHashFormat
* @depends testFilterWhereWithOperatorFormat
*/
public function testAndFilterCompare()
{

Loading…
Cancel
Save