Yii 1.1: defaultpersister

Model behavior to save/load default values to/from user state
12 followers

This is a behavior for CModels (CFormModels, CActiveRecords) 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 / loaded
  • safeOnly - if true, only attributes that are safe in the current scenario will be loaded with loadDefaults(). Default is false.
  • 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

Total 8 comments

#5179 report it
Haensel at 2011/09/21 10:11am
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

#3308 report it
Anupam at 2011/04/01 12:15pm
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.

#3304 report it
Mike at 2011/04/01 09:50am
CDbSession

@anupam_sam: Thanks for your suggestion - the good news is: This already works, if you configure CDbHttpSession as your session 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 :)

#3303 report it
Anupam at 2011/04/01 09:01am
DB 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?

#1997 report it
Mike at 2010/10/28 03:47am
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 users
  • cache - Pro: Fast and probably better scalable. Con: Data lost when cache expires
  • db - Pro: Persistent forever. Con: Requires DB schema/model
  • cookie - Pro: No server storage required. Con: Only applicable for very small amounts of data
#1993 report it
Nemoden at 2010/10/27 10:41am
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.

there should be an option to set different storages for the default values

Would be great!

Now I'd want to erase not necessary words of my previous post: My opinion, - this is convenient.

Good job.

#1992 report it
Mike at 2010/10/27 03:08am
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...

#1988 report it
Nemoden at 2010/10/26 09:23pm
"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.

Leave a comment

Please to leave your comment.

Create extension