'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)

  1. < 1000
  2. <= 1000
  3. = 1000
  4. < 1k
  5. < 1,000
  6. 1000
  7. Null
  8. !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