eadvancedarbehavior The EAdvancedArBehavior extension removes the complexities involved when saving objects with relations

  1. Requirements
  2. Usage

The EAdvancedArBehavior extension takes away some of the complexities involved when saving objects, for example, with MANY_MANY and BELONGS_TO relations.

Requirements

Built on Yii 1.1.6

Usage

The EAdvancedArBehavior extension adds up some functionality to the default possibilites of yii´s ActiveRecord implementation.

To use this extension, just copy this file to your extensions/ directory, add 'import' => 'application.extensions.EAdvancedArBehavior', [...] to your config/main.php and add this behavior to each model you would like to inherit the new possibilities:

public function behaviors(){
      return array( 'EAdvancedArBehavior' => array(
            'class' => 'application.extensions.EAdvancedArBehavior'));
}

Depending on the functionallities you want to enable, you need to set some configuration parameters. This is described below.

Better support for MANY_MANY relations:

Suppose you have a User and Project model having a MANY_MANY relation, for example:

User.php: ~~~ public function relations() {

 return array( .....
     'projects'        => array(self::MANY_MANY, 'Project', 'tbl_project_user(user_id, project_id)') );

} ~~~ Project.php: ~~~ public function relations() {

 return array( .....
     'users'        => array(self::MANY_MANY, 'User', 'tbl_project_user(project_id, user_id)') );

} ~~~

Now you can use it like ~~~ $user = User::model()->findBPk(12) ; $projects = Project::model()->findAll( $criteria ) ; $user->projects = $projects ; $user->save() ; ~~~

Remove relations like ~~~ $user->projects = array() ; // cleans up the relation table // or $user->delete() ; ~~~

Better support for BELONGS_TO relations:

With this extension you can connect two related objects as follows:

$user = new User();
$user->company = Company::model()->find($conditions, $params);
$post->save();

Without this extension, you would have to do this as follows:

$user = new User();
$company = Company::model()->find($conditions, $params) ;
$user->company_id = $company->id ;
$post->save();
HAS_ONE and HAS_MANY

Suppose a User HAS_ONE Address and HAS_MANY Emails, and Address/Email BELONGS_TO User (both have the foreignkey column user_id). So you can do now:

$user = new User() ;
$user->emails = array( $email1, $email2, ... ) ;
$user->address = $address ;
$user->save() ;
Set uninitialized column fields to NULL

See: http://code.google.com/p/yiiext/downloads/detail?name=ensureNull_1.0.1.zip

Use it like

return array(
 'EAdvancedArBehavior' => array(
        'class' => 'application.extensions.EAdvancedArBehavior',
        'useOnUpdate' => false, // set empty fields to NULL only on inserts not updates
    ));
MySQL ONLY: Multiple timespans with CURRENT_TIMESTAMP

Although the title of this section suggests something which cannot be done with MySQL, there is a nice workaround available. This extension provides the means to have a table with one column for the insert time and an other for the last modification time. First, add the following two columns to your table definition

  update_time timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
  created_time timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',

Next, configure the following parameters

return array(
        'EAdvancedArBehavior' => array(
                'class' => 'application.extensions.EAdvancedArBehavior',
                'useNullOnTimestamp' => TRUE,         // set timestamps with a default value of 0000-00-00 00:00 to NULL (for inserts)
                'useOnUpdate' => true,                // required
                'onUpdateTimestamp'=>'update_time',   // column name of the update time
                ),
          );
ignoreRelationsExcept($array=null)

To reduce unnecessary database queries, define the relations which are modified before save():

$model->ignoreRelationsExcept( array('company', 'address') ) ;
$model->save() ;

All relations are ignored except company and address

TODO

add more functionalities (any AR suggestions are welcome!)