Difference between #2 and #1 of Actions code reuse with CAction

unchanged
Title
Actions code reuse with CAction
unchanged
Category
How-tos
unchanged
Tags
CAction, Tutorial
unchanged
Content
##Introduction  
We all know how good 'gii' automates the code for us and we normally
tend to be happy with what that tool offers at the beginning of our Yii learning
curve. But as soon as you start working in larger and larger projects, you
realize that its code is too repetitive to maintain and having a small pitfall
in general actions means to go over and over through them to fix the issues.  

##CAction to the Rescue
I have [already explained how to use widgets as action
providers](http://www.yiiframework.com/wiki/146/how-to-use-a-widget-as-an-action-provider
"How to use a widget as an action provieder") to encapsulate the
actions. What I am going to explain here is how can we easily create an action
to work throughout different controllers.  

Gii provides us normally with the following code on the
'actionCreate': 
~~~
[php]
public function actionCreate()
{
   $model=new ModelName;

   // Uncomment the following line if AJAX validation is needed
   // $this->performAjaxValidation($model);

   if(isset($_POST['ModelName']))
   {
       $model->attributes=$_POST['ModelName'];
       if($model->save())
        
$this->redirect(array('view','id'=>$model->id));
   }

   $this->render('create',array(
       'model'=>$model,
   ));
}
~~~
For a normal project and with the default CMS layout of Yii, does suit our
regular needs and we tend to leave it as it is. But, as I said before, imagine
that we need to include a new parameter in our redirection for example? In order
to avoid that we can tweak a bit the code and develop a general action.

###Step 1 - Creating the Action
For the sake of the example, create the following action and save it on your
protected/components/actions folder
~~~
[php]
class Create extends CAction {

    public function run() {
	$controller = $this->getController();

	// get the Model Name
	$model_class = ucfirst($controller->getId());

	// create the Model
	$model = new $model_class();

	// Uncomment the following line if AJAX validation is needed
	// $this->performAjaxValidation($model);
	if (isset($_POST[$model_class])) {
	    $model->attributes = $_POST[$model_class];

	    if ($model->save())
		$controller->redirect(array('view', 'id' =>
$model->id));
	}
	$controller->render('create', array(
	    'model' => $model,
	));
    }

}
~~~
###Step 2 - Declare the action on the Controller
Once we have the action class created, the only thing we need to do is declare
it in our controller's actions function in order to use it. 

~~~
[php]
public function actions(){
   return array(
      'create'=>'application.components.actions.create',
   );
}
~~~
After declaring the action we can call it:
http://myhost/index.php?r=controller/create, just like any other.  

##Final Notes
In the example above I have used 'getController()' and
'getId()' in order to access the model, but we can actually use
properties as CAction is a class. This could be the declaration of an action
passing the model name to load:
~~~
[php]
// Assuming the action class has the 
// following public properties:
// public model_name
// -----------------
// ModelClass is a test model class name
// -----------------
// On the controller: 
public function actions(){
   return array(
      'create'=>array(
         
'class'=>'application.components.actions.create',
          'model_name'=>'ModelClass',
   );
}
~~~