This is a behavior for [CModel]s ([CFormModel]s, [CActiveRecord]s) that allows to save a set of current attribute values as defaults for the current user and restore them at a later time.
Requirements ¶
Should work with any 1.1.x version. Not tested with 1.0.x.
Usage ¶
When this behavior is attached to a model, the current model values can be saved as default values with a simple command:
$model->saveAsDefaults();
This will save all configured attributes in user state (session). To load these defaults back into the model you can use:
$model->loadDefaults();
It's also possible to save or load only some attributes:
// Will merge with already saved defaults
$model->saveAsDefaults('name');
$model->saveAsDefaults(array('status','project_id'));
$model->loadDefaults('name');
$model->loadDefaults(array('name','project_id'));
To only load attributes that are safe in the current scenario, you can override the configured value of safeOnly
(see below):
// true indicates that only safe attributes should be loaded
$model->loadDefaults(null,true);
Finally to clear the saved default values use:
$model->resetDefaults(); // Reset all defaults
$model->resetDefaults('name'); // Reset specific attribute
Configuration ¶
Like all behaviors this extension has to be configured in the behaviors()
method of a model:
public function behaviors()
{
return array(
'defaults'=>array(
'class'=>'ext.defaultpersister.AttributeDefaultsPersister',
'attributes'=>array('name','status','project_id'),
),
);
}
All attributes that should be saved with saveAsDefaults()
must be listed in the attributes
property of the behavior.
The complete list of configuration options is:
attributes
- list of attribute names that can be saved / loadedsafeOnly
- if true, only attributes that are safe in the current scenario will be loaded withloadDefaults()
. Default isfalse
.stateKeyPrefix
- prefix for the user state key that is used to store defaults. Actual key name will be prefix + model class name. Defaults to 'default_'.
If loadDefaults()
is called before any values where ever saved with saveAsDefaults()
the model is scanned for a method attributeDefaults()
. If this method is found the returned values (name/value pairs) will be set as default. If no such method is available, loadDefaults()
will do nothing in this case.
Since Version 1.1.0 resetDefaults()
can be used to clear all, one or a list of attributes default values.
If YII_DEBUG is true, this behavior will trace some messages under the category application.behavior.defaultpersister
.
Example ¶
One scenario where this behavior can come in handy is e.g. when a model is used as complex filter model for a datagrid. Think of a backend area with pages for users and projects, each showing a filter form and a datagrid. Changes in the filter form trigger a AJAX grid update. Whenever backend personnel accesses such a page the last filter settings should be restored for convenience.
A controller action for this could look like:
public function actionUserList()
{
$filter=new User('filter');
$filter->loadDefaults();
// Set filter attributes on Ajax request and save them as default
if (($isAjax=isset($_GET['ajax'])) && isset($_GET['User']))
{
$filter->attributes=$_GET['User'];
if (!$filter->validate()) // Invalid filter settings!
return;
$filter->saveAsDefaults();
}
// Similar to the search() method in Yii's default CRUD models,
// this method creates a CActiveDataProvider from the current
// attribute values:
$data=$filter->getDataProvider();
if ($isAjax)
// render only the partial for the data grid:
$this->renderPartial('_userGrid',array(
'data'=>$data,
));
else
// render complete view with filter and data grid
$this->render('userList',array(
'filter'=>$filter,
'data'=>$data,
));
}
Resources ¶
Changelog ¶
1.1.0
- Fixed: Model defined attributes that are not in DB will also be set in AR
- Added resetDefaults() method
1.0.0 - initial release
"Big" cookies?
setState stores information in cookies file, so if you overindulge saving defaults into cookies, it might cause problems (google maximum cookies size for different browsers - this article is exists on wiki). Why don't take users defaults from database, put into memcache, so they are available all the time during the session and once session is destroyed, delete memcache key (if did not expired yet) ?
My opinion, - this is convenient, but technically wrong. Cookies is not the place to store defaults.
Re: "Big" cookies?
@So1:
Thanks for your comment, but from all i know user state is not saved in cookies. Cookies are only used
Anything saved with [CWebUser::setState] goes to the session.
Please also have a look at this ticket:
[http://code.google.com/p/yii/issues/detail?id=747]
I agree however that there should be an option to set different storages for the default values. Maybe in a future release...
Re: "big" cookies?
mikl, Ooops, indeed, I was wrong (took a fast look at the code and did not notice you are saving data into session). My apologies.
Would be great!
Now I'd want to erase not necessary words of my previous post:
My opinion, - this is convenient.
Good job.
Feature for different storage
Here some brainstorming on storage types:
session
(user state, default) - Pro: No special requirements. Con: Data lost when session expires; bloats session size if many userscache
- Pro: Fast and probably better scalable. Con: Data lost when cache expiresdb
- Pro: Persistent forever. Con: Requires DB schema/modelcookie
- Pro: No server storage required. Con: Only applicable for very small amounts of dataDB storeage feature using CDbHttpSession?
Hey mikl!
can also add an option to store the values to the Db using the CDbHttpSession.
This will be more persistant and comes handy by storing users 'last entered data' in the forms and when the user login we can show that last entered data as the default values for that form fields.
what do u say?
CDbSession
@anupam_sam:
Thanks for your suggestion - the good news is: This already works, if you configure
CDbHttpSession
as yoursession
application component. So we don't need any other storage mechanism.defaultpersister uses
CWebUser::setState()
to store the default values. This in turn uses the user session to store the values.Note to self:
Maybe i should rewrite the behavior to use Yii::app()->session instead to avoid confusion like this :)
got ur point!
Yeah, i got ur point.
But the reason i thought this is for the flexibility of switching the storage mechanism for this behavior irrespective to what session component is defined in the application component.
Like, for some model will use this to store in $_SESSION and some other model to store in DB.
If it always use the session application component it won't be possible? OR is it?
Plz let me know if i am mistaken. i am planning to use it, so just clarifying.
Thanks, excellent extension
Thanks Mike, this is an excellent extension that is super easy to use and solves the problem in a very elegant way. Thumbs up
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.