Skip to content

Commit

Permalink
Query helper method for filter values containing operators
Browse files Browse the repository at this point in the history
Basic implementation proposal for yiisoft#2022

Shortcomings/todo's:
* filtering on non-scalars (where IN statements) not supported
* Numeric properties with a corresponding validation rule will yield
  errors when they contain an alphanumeric operator. These properties'
  rules should be defined as 'string' or 'safe'.
* no implementation example in Gii code (yet).
  • Loading branch information
lennartvdd committed May 21, 2015
1 parent 0e5723e commit 277a6fd
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 0 deletions.
31 changes: 31 additions & 0 deletions framework/db/QueryTrait.php
Expand Up @@ -375,4 +375,35 @@ public function offset($offset)
$this->offset = $offset;
return $this;
}

/**
* Helper for easy querying on gridview filter input allowing the use some common operators
*
* 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:
* <: the column must be less than the given value.
* >: the column must be greater than the given value.
* <=: the column must be less than or equal to the given value.
* >=: the column must be greater than or equal to the given value.
* <>: the column must not be the same as the given value. Note that when $partialMatch is true, this would mean the value must not be a substring of the column.
* =: the column must be equal to the given value.
* none of the above: use the $defaultOperator
*
* Note that when the value is empty, no comparison expression will be added to the search condition.
*
* @param string $name column name
* @param scalar $value column value
* @param string $defaultOperator Defaults to =, performing an exact match.
* For example: use 'like' for partial matching
*/
public function compare($name, $value, $defaultOperator = '=')
{
$matches=[];
if (preg_match("/^(<>|>=|>|<=|<|=)/", $value, $matches)) {
$op = $matches[1];
$value = substr($value, strlen($op));
} else {
$op = $defaultOperator;
}
$this->andFilterWhere([$op, $name, $value]);
}
}
30 changes: 30 additions & 0 deletions tests/framework/db/QueryTest.php
Expand Up @@ -220,6 +220,36 @@ public function testCount()
$this->assertEquals(2, $count);
}

/**
* @depends testFilterWhere
*/
public function testCompare()
{
$query = new Query;

$query->compare('name', null);
$this->assertNull($query->where);

$query->compare('name', '');
$this->assertNull($query->where);

$query->compare('name', 'John Doe');
$condition = ['=', 'name', 'John Doe'];
$this->assertEquals($condition, $query->where);

$condition = ['and', $condition, ['like', 'name', 'Doe']];
$query->compare('name', 'Doe', 'like');
$this->assertEquals($condition, $query->where);

$condition = ['and', $condition, ['>', 'rating', '9']];
$query->compare('rating', '>9');
$this->assertEquals($condition, $query->where);

$condition = ['and', $condition, ['<=', 'value', '100']];
$query->compare('value', '<=100');
$this->assertEquals($condition, $query->where);
}

/**
* @see https://github.com/yiisoft/yii2/issues/8068
*
Expand Down

0 comments on commit 277a6fd

Please sign in to comment.