使用独立动作
在Yii中,你可以定义控制器动作作为独立的类,然后连接它们到你的控制器上。这将会帮助你复用一些常用功能。
例如,你可以为自动完成字段移动后端到一个动作中并保存,而不需要再次一遍一遍的写。
另外一个例子是,我们可以创建所有的CRUD操作作为分开的独立动作。我们将会写、创建、查看和删除模型的动作,并查看模型的操作列表。
准备
- 按照官方指南http://www.yiiframework.com/doc-2.0/guide-start-installation.html的描述,使用Composer包管理器创建一个新的应用。
- 创建
post
表。使用如下命令创建migration:
./yii migrate/create create_post_table
- 更新刚刚创建的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);
}
}
- 使用如下命名安装所有的migration:
./yii migrate up
- 使用Gii创建
Post
。
如何做…
- 创建独立动作
@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
]);
}
}
}
- 创建独立动作
@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']);
}
}
- 创建独立动作
@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
]);
}
}
- 创建独立动作
@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
]);
}
}
- 创建视图文件
@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(); ?>
- 创建视图文件
@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,
]); ?>
- 创建视图文件
@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中通过复写动作方法定义它。
- 运行
post/index
:
工作原理…
每一个控制器可以从独立动作中创建,就像是在拼图。区别是你可以是独立动作非常灵活,并在很多地方复用。
在我们的动作中,我们定义了modelClass
公共属性,它能在PostController
的actions
方法中设置一个指定的类。
参考
欲了解更多信息, 参考http://www.yiiframework.com/doc-2.0/guide-structurecontrollers.html#standalone-actions。