In Yii, you can define controller actions as separate classes and then connect them to your controllers. This way, you can reuse some common functionality.
For example, you can move the backend for autocomplete fields to an action and save some time by not having to write it over and over again.
Another simple example that we will review is deleting a model.
yiic webapp
.CREATE TABLE `post` ( `id` int(10) unsigned NOT NULL auto_increment, `created_on` int(11) unsigned NOT NULL, `title` varchar(255) NOT NULL, `content` text NOT NULL, PRIMARY KEY (`id`) ); CREATE TABLE `user` ( `id` int(10) unsigned NOT NULL auto_increment, `username` varchar(200) NOT NULL, `password` char(40) NOT NULL, PRIMARY KEY (`id`) );
Post
and User
models using Gii. Add some data to the tables.protected/controllers/PostController.php
. It is a usual delete action for posts:class PostController extends CController { function actionIndex() { $posts = Post::model()->findAll(); $this->render('index', array( 'posts' => $posts, )); } function actionDelete($id) { $post = Post::model()->findByPk($id); if(!$post) throw new CHttpException(404); if($post->delete()) $this->redirect('post/index'), throw new CHttpException(500); } }
We have defined two actions. One lists all posts and another deletes a specified post if it exists and redirects back to the index
action. You can try these using /index.php?r=post/index
and /index.php?r=post/delete&id=1
.
DeleteAction.php
in your protected/components
directory as follows:class DeleteAction extends CAction { function run() { if(empty($_GET['id'])) throw new CHttpException(404); $post = Post::model()->findByPk($_GET['id']); if(!$post) throw new CHttpException(404); if($post->delete()) $this->redirect('post/index'), throw new CHttpException(500); } }
actionDelete
; we will not need it anymore. Then, add the actions
method:class PostController extends CController { function actions() { return array( 'delete' => 'DeleteAction', ); } … }
/index.php?r=post/delete&id=2
again. It should work exactly the same way as it did last time. Now, we are using the external delete
action for PostController
, but what about UserController
? To use DeleteAction
with UserController
we need to customize it first. We do this as follows:class DeleteAction extends CAction { public $pk = 'id'; public $redirectTo = 'index'; public $modelClass; function run() { if(empty($_GET[$this->pk])) throw new CHttpException(404); $model = CActiveRecord::model($this->modelClass)->findByPk($_GET[$this->pk]); if(!$model) throw new CHttpException(404); if($model->delete()) $this->redirect($this->redirectTo); throw new CHttpException(500); } }
PostController
and UserController
. For PostController
, we do this as follows:class PostController extends CController { function actions() { return array( 'delete' => array( 'class' => 'DeleteAction', 'modelClass' => 'Post', ); ); } … }
UserController
, we do this as follows:class UserController extends CController { function actions() { return array( 'delete' => array( 'class' => 'DeleteAction', 'modelClass' => 'User', ), ); } … }
/index.php?r=post/delete&id=3
and /index.php?r=user/delete&id=1
.This way, you can save yourself a lot of time by implementing and reusing external actions for tasks of a similar type.
Every controller can be built from external actions like a puzzle from pieces. The difference is that you can make external actions very flexible and reuse them in many places. In the final version of DeleteAction
, we defined some public properties. As DeleteAction
is a component, we can set its properties through the configuration file. In our case, we pass the configuration into the action's controller method, used to add actions to a module.
For further information, refer to the following URLs:
13.59.231.155