官术网_书友最值得收藏!

Using external actions

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.

Getting ready

  1. Set up a new application using yiic webapp.
  2. Create a database schema with the following script:
    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`)
    );
  3. Generate the Post and User models using Gii. Add some data to the tables.

How to do it...

  1. Let's write 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.

  2. Now, let's do the same in a separate action class. Create 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);
       }
    }
  3. Let's use it inside our controller. Delete actionDelete; we will not need it anymore. Then, add the actions method:
    class PostController extends CController
    {
       function actions()
       {
          return array(
             'delete' => 'DeleteAction',
          );
       }
    
       …
    
    }
  4. Try /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);
       }
    }
  5. Now, we can use this action for both PostController and UserController. For PostController, we do this as follows:
    class PostController extends CController
    {
       function actions()
       {
          return array(
             'delete' => array(
                'class' => 'DeleteAction',
                'modelClass' => 'Post',
             );
          );
       }
    
       …
    
    }
  6. For UserController, we do this as follows:
    class UserController extends CController
    {
       function actions()
       {
          return array(
             'delete' => array(
                'class' => 'DeleteAction',
                'modelClass' => 'User',
             ),
          );
       }
    
       …
    
    }
  7. Try using /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.

How it works...

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.

There's more…

For further information, refer to the following URLs:

主站蜘蛛池模板: 乌审旗| 鱼台县| 石狮市| 班戈县| 油尖旺区| 富锦市| 灵寿县| 锡林浩特市| 余干县| 东辽县| 英吉沙县| 简阳市| 永州市| 西青区| 陕西省| 公安县| 辉南县| 克拉玛依市| 贡觉县| 禄丰县| 临清市| 枝江市| 津南区| 宁德市| 武清区| 乌审旗| 宜兰县| 大荔县| 东丽区| 玉环县| 防城港市| 扎兰屯市| 巧家县| 永年县| 东光县| 深泽县| 治多县| 容城县| 双辽市| 浮山县| 秀山|