Creating a customized version of Yii's CActiveRecord

Last updated:

class MyCActiveRecord extends CActiveRecord {
    public static function fetch_or_create_from_attributes($attributes_array) {
        $model = static::model()->findByAttributes($attributes_array);
        if (!is_null($model)) {
            return $model;
        } else {
            $model = new static;
            foreach ($attributes_array as $key => $value) {
                $model->$key = $value;
            }
            try {
                if ($model->save()) {
                    return $model;
                } else {
                    throw new RuntimeException('Could not create model');
                }
            } catch (Exception $e) {
                throw new RuntimeException('Could not create model.');
            }
        }
    }
}

in all subclasses, add this:

class Reference extends MyCActiveRecord {
    public static function model($className=__CLASS__) {
        return CActiveRecord::model($className);
    }
    //class code.....

Explanation:

Very often you may find yourself needing to fetch a model instance if it exists or create it if it doesn't. You may end up with boilerplate code like this all around your app:

$model_instance = YourModel::model()->findByAttributes(array("attribute1"=>"value1","attribute2"=>"value2","attribute3"=>"value3"));
if(is_null($model_instance)){
    //create new model instance using those 
    //attributes and return the new instance
}

Of course, a refactoring was due for this. With the code above, you can abstract away from all that testing which doesn't really add any value to your app.

Dialogue & Discussion