View on GitHub

yii2-cookbook-chinese

Yii Application Development Cookbook(Third Edition)中文翻译

使用独立动作

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

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

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

准备

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

如何做…

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

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

  1. 运行post/index

工作原理…

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

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

参考

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