Refactoring Named And Parameterized Named Scopes

For most of my ActiveRecords, I used many of similar named scopes (the one inside the scopes() method) and parameterized named scopes quite repetitively.

For example, I have an attribute ‘removed’ for most of my model tables.

And in the CActiveRecord class, I have to put this inside the scopes method.




'notRemoved' => array(

  'condition' => 'removed = 0'

),



and another example, i have another field created which stores datetime when the record created. and i have to put this also




'newest' => array(

  'order' => 'createdTime DESC'

),



I’m wondering if this can be refactored.

you can override/extend the active record class for such common tables and inside this overriden class you can add this colunm


'notRemoved' => array(

  'condition' => 'removed = 0'

),

'newest' => array(

  'order' => 'createdTime DESC'

),

Actually I’m thinking about something that can be attachable like behavior.




/**

 * RemovableBehavior adds new parameterized scope for filtering records

 * that are not flagged as removed.

 * @property-read CActiveRecord $owner

 */

class RemovableBehavior extends CBehavior {


   /**

    * The field name.

    */

   public $fieldName = 'removed';


   /**

    * Scope

    * @return CActiveRecord the modified model for method chaining.

    */

   public function notRemoved(){

       $t = $this->owner->getTableAlias();

       $param = ":t". rand(10000, 99999);

       $this->owner->getCdbCriteria()->mergeWith(array(

            'condition' => "`{$t}`.`{$this->fieldName} = {$param}",

            'params' => array(

                $param => 0,

            ),

       ));

       return $this->owner;

   }

}



And in the model we can insert just a line




class MyModel extends CActiveCriteria {

    public function behaviors(){

        return array(

            'removable' => 'RemovableBehavior',

        );

    }

}



And we can just use it like the usual.




$model = MyModel::model()->notRemoved()->findAll();



The good thing is that we can add multiple scopes inside the behavior, e.g. the notRemoved() counterpart removed().




   public function removed(){

       $t = $this->owner->getTableAlias();

       $param = ":t". rand(10000, 99999);

       $this->owner->getCdbCriteria()->mergeWith(array(

            'condition' => "`{$t}`.`{$this->fieldName} = {$param}",

            'params' => array(

                $param => 1,

            ),

       ));

       return $this->owner;

   }



I haven’t tested this, so this may work or may not.

Any other idea?