I did not completely understand your need for saving/restoring…
Do you want to "remember" the filter settings even if the user goes to some other webpage that is not your… in this case you would need to remember that in a database…
If you want to remember it only while the user is logged on your site… than you need to use sessions as suggested by Mahdi…
Anyway this functionality is not built in… you need to implement the saving of the filter values… and then in $model->search() you need to retreive that values if they exist… and apply them…
Now I am thinking if I should come up with a behavior class for this, could you help me if it’s possible for the usage and if so answer the following questions:
where do I place behaviors classes?
how do I do/attach a behavior to be used by the search method?
how do I make sure that CGridView uses the behavior, so it retrieves and populates back the values from session?
how can the behavior also populate the _form.php files (probably subscribing into the CActiveForm or the model?) what options do I have here?
You can make a behavior if you need to use this in many different CGridViews… the main problem is how the behavior will know what fields to check… how many there are… and so on…
If you want to go with the behavior here is a start:
Let’s say we want to call this behavior mysearch… you need to create a file mysearch.php… you can put it in the protected/components folder
mysearch.php
<?php
class mySearch extends CActiveRecordBehavior
{
public $field1;
public function preSearch()
{
$this->owner->{$this->field1}='Pr';
}
}
Then in the model you attach the behavior and define the field like:
public function behaviors(){
return array(
'mySearch'=>array(
'class'=>'application.components.mySearch',
'field1'=>'name', //.. name is the attribute from the model
),
);
}
Finaly in the model search method you add the call to the preSearch() method like:
public function search()
{
$this->preSearch();
$criteria=new CDbCriteria;
...
This way by calling preSearch() we are setting the name attribute to "Pr"
I was thinking on the behavior method… that’s why I added to it the field1… that in the model should be set to the actual attribute you need to set… like ‘name’
I just tried to make this working… and here is the complete solution
First we create the behavior - mysearch.php - put it in protected/components
<?php
class mySearch extends CActiveRecordBehavior
{
public function readSearchValues()
{
$modelName=get_class($this->owner);
$attributes=$this->owner->getSafeAttributeNames();
foreach($attributes as $attribute)
{
if(null!=($value=Yii::app()->user->getState($modelName.$attribute,null)))
{
$this->owner->$attribute=$value;
Yii::app()->user->setState($modelName.$attribute,1,1);
}
}
}
public function saveSearchValues()
{
$modelName=get_class($this->owner);
$attributes=$this->owner->getSafeAttributeNames();
foreach($attributes as $attribute)
Yii::app()->user->setState($modelName.$attribute,$this->owner->$attribute);
}
}
In the model you need to attach the behavior
public function behaviors(){
return array(
'mySearch'=>array(
'class'=>'application.components.mySearch',
),
);
}
And in the controller we decide if to read or to save the values… like
public function actionAdmin()
{
$model=new Company('search');
$model->unsetAttributes(); // clear any default values
if(isset($_GET['Company']))
{
$model->attributes=$_GET['Company'];
$model->saveSearchValues();
}
else
$model->readSearchValues();
$this->render('admin',array(
'model'=>$model,
));
}
1). If I reload the pages twice or more (without navigation away), the page looses the values
2). In the safe enumeration I have values from relations. like `address1 and I get Exception when the behavior class wants to access it.
How can I make sure all relations have been loaded before trying to access the values from them?
3). Can I attach this behavior more generally ? Like use of afterConstruct and to skip the step needed in [font="monospace"][size="2"]actionAdmin(). This question should read: can I move into the behavior class definition, the code present in actionAdmin to handle save/read values?[/size][/font]
2 - the behavior class is called from actionAdmin() after the model is created… so everything should be set already… this would need debugging to see what is the real cause of the error
3 - this behavior needs to be called only for an action that renders a CGridView and you need to decide when to save the values to SESSION and when to read them…
can't see a way to make this generally... additionaly CGridView does not fire any event...
address1 is in safe list because it is used by an alias
public function search() {
$criteria = new CDbCriteria;
$criteria->compare('address1', $this->residence_id, true);
$criteria->with = array('residence' => array('select' => 'address1'));
return new CActiveDataProvider(get_class($this), array(
'criteria' => $criteria,
));
}
As you see in the code the address1 is actually $this->residence->address1 and this is listed in the ‘safe’ enumeration because needs to get input. If I don’t list address1 in the safe list, it doesn’t get the input.
so how do I load all the relations and check this against it?
for 3)
I had to add to the behavior this:
public function afterConstruct($event) {
if ($this->owner->scenario == 'search') {
$this->owner->unsetAttributes();
if (isset($_GET[get_class($this->owner)])) {
$this->owner->attributes = $_GET[get_class($this->owner)];
$this->owner->saveSearchValues();
} else {
$this->owner->readSearchValues();
}
}
}
So $this->residence_id is the attribute that gets the input in the CGridView filter… and that attribute should be on the safe validator list… I don’t see why would address1 be on that list if it’s not used for massive assignment.