Filtrowanie Od Daty Do Daty

Witam. Dosyć długo mnie nie było na forum, lecz niestety znowu powracam z problemem. Mam CGridView z danymi wczytanymi od CActiveDataProvider -> kontroler:




...

$dataProvider=new CActiveDataProvider('XYZ', array(

                'criteria'=>array(

                    'condition'=>'user_id='.Yii::app()->user->id,

                    'order'=>'data DESC',

                ),

                'pagination'=>array(

                    'pageSize'=>3,

                )

));

...

Chciałbym użytkownikom dodać możliwość wyświetlania danych od konkretnej do konkretnej daty. W sieci jest parę przykładów jak to zrobić, lecz wszystko są oparte o zmodyfikowanie funkcji _search w modelu. Jednak ja w CGridView nie korzystam z $model->search tylko ładuje CActiveDataProvider. W jaki sposób to rozwiązać?

Chodzi o to, aby ustawić criteria w dataProviderze. Jeśli nie chcesz opakować przygotowania dataProvidera w search() to zrób to sam bezpośrednio tam, gdzie go definiujesz.

Zrobiłem tak ale nie działa i w logach nie ma w ogóle BETWEEN

Kontroler:


public function actionXXXXX($from_date="",$to_date="") 

...

            $dataProvider=new CActiveDataProvider('XYZ', array(

                'criteria'=>array(

                    'condition'=>'user_id='.Yii::app()->user->id,

                ),

                'pagination'=>array(

                    'pageSize'=>3,

                )

            ));

            $dataProvider->criteria->addBetweenCondition('time',''.$from_date.'',''.$to_date.'','AND'); 

...

i jako post są wysyłane przykładowo takie dane:

from_date: 2013-09-01

to_date: 2013-09-30

Coś znowu nie tak zrobiłem?

Prawdopodobnie CActiveDataProvider.getCriteria() zwraca Ci kopię, więc to co tam zmieniasz nie jest zapamiętywane. Nie możesz przygotować obiektu kryteria zanim utworzysz dataProvider i przekazać go do niego?

Skoro już musisz tworzyć DataProvider’a w kontrolerze i opisywać go logiką, to:

w kluczu ‘condition’ dodaj between’a i po kłopocie.

Coś na wzór:





$from_date = $this->dbConnection->quoteValue($from_date);

$to_date = $this->dbConnection->quoteValue($to_date);


$dataProvider=new CActiveDataProvider('XYZ', array(

                'criteria'=>array(

                    'condition'=>'user_id='.Yii::app()->user->id . ' AND time BETWEEN ' . $from_date . ' AND ' . $to_date,

                    'order'=>'data DESC',

                ),

                'pagination'=>array(

                    'pageSize'=>3,

                )

));



…przy czym to jest ANTYWZORZEC pisać takie przeczy w kontrolerze.

Utwórz w modelu metody scope’owe i użyj je w kontekscie scenariusza “search”:




// gdzieś w Twoim modelu 


public function dateBetween($from_date, $to_date) {

    $this->dbCriteria->mergeWith(array(

        'condition' => 'time BETWEEN :from_date AND :to_date',

        'params' => array(

            ':from_date' => $from_date,

            ':to_date'   => $to_date,

        ),

    ));

    return $this;

}


// jesli zawsze wybierasz dane w kontekscie usera, to mozesz dodać ten kod do metody CActiveRecord::defaultScope()

public function currentUser() {

    $this->dbCriteria->mergeWith(array(

        'condition'=>'user_id='.Yii::app()->user->id

    ));

    return $this;

}




Co do sortowania to już w metodzie search() możesz poustawiać defaultOrder, pageSize etc.

…użycie w kontrolerze, coś na kształt:




// kontroler

$model = new XYZ('search');

$dataProvider = $model

    ->dateBetween($from_date, $to_date)

    ->currentUser()

    ->search();