使用独立动作

在Yii中,你可以定义控制器动作作为独立的类,然后连接它们到你的控制器上。这将会帮助你复用一些常用功能。

例如,你可以为自动完成字段移动后端到一个动作中并保存,而不需要再次一遍一遍的写。

另外一个例子是,我们可以创建所有的CRUD操作作为分开的独立动作。我们将会写、创建、查看和删除模型的动作,并查看模型的操作列表。

准备

  1. 按照官方指南http://www.yiiframework.com/doc-2.0/guide-start-installation.html的描述,使用Composer包管理器创建一个新的应用。
  2. 创建post表。使用如下命令创建migration:
  1. ./yii migrate/create create_post_table
  1. 更新刚刚创建的migration的方法和导出的类列表:
  1. <?php
  2. use yii\db\Schema;
  3. use yii\db\Migration;
  4. class m150719_152435_create_post_table extends Migration
  5. {
  6. const TABLE_NAME = '{{%post}}';
  7. public function up()
  8. {
  9. $tableOptions = null;
  10. if ($this->db->driverName === 'mysql') {
  11. $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE=InnoDB';
  12. }
  13. $this->createTable(self::TABLE_NAME, [
  14. 'id' => Schema::TYPE_PK,
  15. 'title' => Schema::TYPE_STRING.'(255) NOT NULL',
  16. 'content' => Schema::TYPE_TEXT.' NOT NULL',
  17. ], $tableOptions);
  18. for ($i = 1; $i < 7; $i++) {
  19. $this->insert(self::TABLE_NAME, [
  20. 'title' => 'Test article #'.$i,
  21. 'content' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. '
  22. .'Sed sit amet mauris est. Sed at dignissim dui. '
  23. .'Phasellus arcu massa, facilisis a fringilla sit amet, '
  24. .'rhoncus ut enim.',
  25. ]);
  26. }
  27. }
  28. public function down()
  29. {
  30. $this->dropTable(self::TABLE_NAME);
  31. }
  32. }
  1. 使用如下命名安装所有的migration:
  1. ./yii migrate up
  1. 使用Gii创建Post

如何做…

  1. 创建独立动作@app/actions/CreateAction.php
  1. <?php
  2. namespace app\actions;
  3. use Yii;
  4. use yii\base\Action;
  5. class CreateAction extends Action
  6. {
  7. public $modelClass;
  8. public function run()
  9. {
  10. $model = new $this->modelClass();
  11. if ($model->load(Yii::$app->request->post()) && $model->save()) {
  12. $this->controller->redirect(['view', 'id' => $model->getPrimaryKey()]);
  13. } else {
  14. return $this->controller->render('//crud/create', [
  15. 'model' => $model
  16. ]);
  17. }
  18. }
  19. }
  1. 创建独立动作@app/actions/DeleteAction.php
  1. <?php
  2. namespace app\actions;
  3. use yii\base\Action;
  4. use yii\web\NotFoundHttpException;
  5. class DeleteAction extends Action
  6. {
  7. public $modelClass;
  8. public function run($id)
  9. {
  10. $class = $this->modelClass;
  11. if (($model = $class::findOne($id)) === null) {
  12. throw new NotFoundHttpException('The requested page does not exist.');
  13. }
  14. $model->delete();
  15. return $this->controller->redirect(['index']);
  16. }
  17. }
  1. 创建独立动作@app/actions/IndexAction.php
  1. <?php
  2. namespace app\actions;
  3. use yii\base\Action;
  4. use yii\data\Pagination;
  5. class IndexAction extends Action
  6. {
  7. public $modelClass;
  8. public $pageSize = 3;
  9. public function run()
  10. {
  11. $class = $this->modelClass;
  12. $query = $class::find();
  13. $countQuery = clone $query;
  14. $pages = new Pagination([
  15. 'totalCount' => $countQuery->count(),
  16. ]);
  17. $pages->setPageSize($this->pageSize);
  18. $models = $query->offset($pages->offset)
  19. ->limit($pages->limit)
  20. ->all();
  21. return $this->controller->render('//crud/index', [
  22. 'pages' => $pages,
  23. 'models' => $models
  24. ]);
  25. }
  26. }
  1. 创建独立动作@app/actions/ViewAction.php
  1. <?php
  2. namespace app\actions;
  3. use yii\base\Action;
  4. use yii\web\NotFoundHttpException;
  5. class ViewAction extends Action
  6. {
  7. public $modelClass;
  8. public function run($id)
  9. {
  10. $class = $this->modelClass;
  11. if (($model = $class::findOne($id)) === null) {
  12. throw new NotFoundHttpException('The requested page does not exist.');
  13. }
  14. return $this->controller->render('//crud/view', [
  15. 'model' => $model
  16. ]);
  17. }
  18. }
  1. 创建视图文件@app/views/crud/create.php
  1. <?php
  2. use yii\helpers\Html;
  3. use yii\widgets\ActiveForm;
  4. /*
  5. * @var yii\web\View $this
  6. */
  7. ?>
  8. <h1><?= Yii::t('app', 'Create post'); ?></h1>
  9. <?php $form = ActiveForm::begin();?>
  10. <?php $form->errorSummary($model); ?>
  11. <?= $form->field($model, 'title')->textInput() ?>
  12. <?= $form->field($model, 'content')->textarea() ?>
  13. <?= Html::submitButton(Yii::t('app', 'Create'), ['class' =>
  14. 'btn btn-primary']) ?>
  15. <?php ActiveForm::end(); ?>
  1. 创建视图文件@app/views/crud/index.php
  1. <?php
  2. use yii\widgets\LinkPager;
  3. use yii\helpers\Html;
  4. use yii\helpers\Url;
  5. /*
  6. * @var yii\web\View $this
  7. * @var yii\data\Pagination $pages
  8. * @var array $models
  9. */
  10. ?>
  11. <h1>Posts</h1>
  12. <?= Html::a('+ Create a post', Url::toRoute('post/create')); ?>
  13. <?php foreach ($models as $model):?>
  14. <h3><?= Html::encode($model->title);?></h3>
  15. <p><?= Html::encode($model->content);?></p>
  16. <p>
  17. <?= Html::a('view', Url::toRoute(['post/view', 'id' =>
  18. $model->id]));?> |
  19. <?= Html::a('delete', Url::toRoute(['post/delete', 'id'
  20. => $model->id]));?>
  21. </p>
  22. <?php endforeach; ?>
  23. <?= LinkPager::widget([
  24. 'pagination' => $pages,
  25. ]); ?>
  1. 创建视图文件@app/views/crud/view.php
  1. <?php
  2. use yii\helpers\Html;
  3. use yii\helpers\Url;
  4. /*
  5. * @var yii\web\View $this
  6. * @var app\models\Post $model
  7. */
  8. ?>
  9. <p><?= Html::a('< back to posts', Url::toRoute('post/index'));
  10. ?></p>
  11. <h2><?= Html::encode($model->title);?></h2>
  12. <p><?= Html::encode($model->content);?></p>

为了使用独立动作,我们在动作map中通过复写动作方法定义它。

  1. 运行post/index

使用独立动作 - 图1

工作原理…

每一个控制器可以从独立动作中创建,就像是在拼图。区别是你可以是独立动作非常灵活,并在很多地方复用。

在我们的动作中,我们定义了modelClass公共属性,它能在PostControlleractions方法中设置一个指定的类。

参考

欲了解更多信息, 参考http://www.yiiframework.com/doc-2.0/guide-structurecontrollers.html#standalone-actions