How to filter by datetime with < operator

Hi there,

I’m trying to filter my rest api data by a datetime value using operator < and by using the ActiveDataFilter.

I want to achieve something like this
/index.php?r=somecontroller%2Findex&filter[timestamp]<2020-12-21%2000%3A31%3A44

Filtering works fine when I try to filter with equal (=) operation, but when I use operator < the datetime value is not being parsed correctly.

Model is implemented like this:

class SomeModel extends Model
{
    public $timestamp;
    public function rules()
    {
        return [
            ['timestamp', 'datetime', 'format' => 'php:Y-m-d H:i:s'],
        ];
    }
}

and data provider is implemented like:

public function indexDataProvider()
{
        $model = new $this->modelClass;
        $query = $model::find();
        
        $filter = new ActiveDataFilter([
            'searchModel' => 'models\SomeModel'
        ]);
        
        $filterCondition = null;

        if ($filter->load(\Yii::$app->request->get())){
            $filterCondition = $filter->build();
        }
        
        if($filterCondition === null || $filterCondition === false || sizeof($filterCondition)===0)
            throw new \yii\web\ForbiddenHttpException();
        
        if ($filterCondition !== null) {
            $query->andWhere($filterCondition);
        }
        
        $dataProvider = new ActiveDataProvider([
            'query' => $query,
            'pagination' => [
                'pageSize' => 4,
            ],
        ]);
        return $dataProvider;
    }

Any directions here are much appreciated.

Thank you

1 Like

Try filter[timestamp][lt]=...

1 Like

ty, that’s it! :muscle:

Hm,
I have same problem, sending request like filter[date_to][lt]=2021-02-01 and in vendor/yiisoft/yii2/data/DataFilter.php:536

foreach ($condition as $key => $value) {
    $method = 'validateAttributeCondition';
        if (isset($this->filterControls[$key])) {

        }
}

$condition variable looks like:

array (
  'date_to' => 
  array (
    'lt' => '2021-02-01',
  ),
)

so it doesn’t works.

Controller use standard config like:

$actions['index']['dataFilter'] = [
    'class' => ActiveDataFilter::class,
    'searchModel' => MyModelSearch::class,
];

IndexAction build filters like:

$filter = null;
if ($this->dataFilter !== null) {
    $this->dataFilter = Yii::createObject($this->dataFilter);
    if ($this->dataFilter->load($requestParams)) {
        $filter = $this->dataFilter->build();
        if ($filter === false) {
            return $this->dataFilter;
        }
    }
}

where is problem?

Are you sure $condition looks like that? Before hitting validateConditio() it should run through normalization methods that flattens it.

Trace:

  1. IndexAction $filter = $this->dataFilter->build();
  2. Model->validate()
  3. Validator->validateAttributes()
  4. InlineValidator->validateAttribute()
  5. DataFilter->validateFilter(), and here $value is:
array (
  'date_to' => 
  array (
    'lt' => '2021-02-01',
  ),
)
  1. DataFilter->validateCondition()
  2. DataFilter->validateAttributeCondition()
  3. DataFilter->validateOperatorCondition

Hm, and all pass ok (strange, I don’t change anything just reboot my computer ;-)), and in the end problem was in ModelSearch class, gii generated code mark attributes date_to and date_from as “safe” instead of “date” - with case filter validation errors.