'Yii2 GridView multiple filters in one column (<, >, = )
I'm trying to filter a numeric value by values greater, lesser or equal to the one given in input.
So far I have managed to filter individually or at most by >= or <=
->andFilterWhere(['<=', 'production_order.qnt', $this->qnt])
but I can't find a solution to filter by writing in the input "<500" or "> 500" because in the rules I set this value ( qnt ) as integer.
public function rules()
{
return [
[['product_routing_id', 'qnt', 'qnt_worked', 'production_status_id', 'production_order_id', 'acceptance_order_id', 'customer_id', 'product_id', 'casting_id', 'trash'], 'integer'],
}
Do i need a custom filter for it? Any ideas? Thanks
Solution 1:[1]
Here is the code I have created for this (and yes, you need to change the rule to string because "<" is not an integer, it is a string)
First I have a public static function which is contained in a class called NumberFilter. NumberFilter contains one public function getArray()
This allows the user to apply any of the following filters (obviously it allows greater than as well)
- < 1000
- <= 1000
- = 1000
- < 1k
- < 1,000
- 1000
- Null
- !null
{
public static function getArray($param, $filterString)
{
if (empty($filterString)){
return [];
}
// remove any whitespace
$filterString = trim($filterString);
$filterString = str_replace(" ", "", $filterString);
$filterString = str_replace(",", ".", $filterString);
$filterString = strtolower($filterString);
if (substr($filterString, 0, 2) == ">=") {
$n = substr($filterString, 2);
$n = self::applyMultiplier($n);
if (is_numeric($n))
return [">=", $param, (integer)$n];
} else if (substr($filterString, 0, 1) == ">") {
$n = substr($filterString, 1);
$n = self::applyMultiplier($n);
if (is_numeric($n))
return [">", $param, (integer)$n];
} else if (substr($filterString, 0, 2) == "<=") {
$n = substr($filterString, 2);
$n = self::applyMultiplier($n);
if (is_numeric($n))
return ["<=", $param, (integer)$n];
} else if (substr($filterString, 0, 1) == "<") {
$n = substr($filterString, 1);
$n = self::applyMultiplier($n);
if (is_numeric($n))
return ["<", $param, (integer)$n];
} else if (substr($filterString, 0, 1) == "=") {
$n = substr($filterString, 1);
$n = self::applyMultiplier($n);
if (is_numeric($n))
return [$param => (integer)$n];
} else if ($filterString == "null") {
return [$param => NULL];
} else if ($filterString == "!null") {
return ['NOT', [$param => NULL]];
} else if (is_numeric($filterString)) {
return [$param => (integer)$filterString];
}
Yii::$app->session->setFlash('error', 'The filter was not a valid number. Please try again');
return '0=1'; // invalid query - return no results
}
// used to replace k with 1,000 etc
private static function applyMultiplier($n)
{
if (strpos($n, "k") !== false) {
$n = str_replace("k", "", $n);
$n = doubleval($n) * 1000;
if (is_numeric($n))
return $n;
}
if (strpos($n, "m") !== false) {
$n = str_replace("m", "", $n);
$n = doubleval($n) * 1000000;
if (is_numeric($n))
return $n;
}
if (strpos($n, "b") !== false) {
$n = str_replace("b", "", $n);
$n = doubleval($n) * 1000000000;
if (is_numeric($n))
return $n;
}
// nothing to do
return $n;
}
}
From within the DataProvider, I can call the filter as follows:
$query->andWhere(NumberFilter::getArray('FIELD_NAME', $this->FIELD_NAME));
This function will return the array needed by Yii, for example:
['>' , 'FIELD_NAME' , 1000]
Solution 2:[2]
You should use between
andFilterWhere(['between', 'created_at', $start_date, $end_date])
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 |