原文出处：https://jellybool.com/post/programming-with-yii2-getting-started-with-install-and-hello-world

嗯，今天起打算写一个系列教程来过一遍Yii2，没错，我就是来安利大家使用Yii2的。至于最爱的Laravel，后面是打算会有教程的，只是不知道是系列博文还是直接录视频而已，因为Laravel貌似想讲的东西实在是太多了。给Laravel发完金水之后，还是回到Yii2本身吧。

额，如果你还没听说过什么是Yii，可以直接看下面的链接：

http://www.yiiframework.com/

安装Yii2

打算从头开始，所以，连安装Yii2也稍微写一点吧。安装Yii2最好的方式就是使用composer：

      composer global require "fxp/composer-asset-plugin:~1.0.3"

composer create-project --prefer-dist yiisoft/yii2-app-basic helloYii

等待一小段时间之后（如果等太久或直接报错，请使用VPN），在这两步你应该会看到类似下面的信息：

      Updating dependencies (including require-dev)
  - Installing fxp/composer-asset-plugin (v1.0.3)
    Downloading: 100%

Writing lock file
Generating autoload files
> yii\composer\Installer::postCreateProject
chmod('runtime', 0777)...done.
chmod('web/assets', 0777)...done.
chmod('yii', 0755)...done.

这里的第一条命令跟官方文档的有稍微的差别，官方文档还是停留在fxp/composer-asset-plugin:~1.0.0，在我写这篇文章的时候，最新版本为fxp/composer-asset-plugin:~1.0.3。所以这里会有一些些不一样。

注，我直接将helloYii项目放在了桌面，你可以根据自己的喜好调整目录

安装完Yii2之后，进入到项目的web/目录：

      cd helloYii/web

开启PHP内置服务器：

      php -S localhost:8999

然后再浏览器输入localhost:8999，你就可以看到下面的页面了：

这里需要说明的是：我是在mac下进行的开发，并且处于便捷的原因，我后续也会一直使用PHP内置服务器，也就是说本教程的localhost:8999是我默认的首页地址。至于用MAMP for OS X的用户，你可以直接配置MAMP

      cd /Applications/MAMP/htdocs
ln -s ~/Desktop/helloYii/ /Applications/MAMP/htdocs/helloYii

然后你可以访问这样的地址：http://localhost:8888/helloYii/web，不出意外，你也可以看Yii默认的可爱首页了。

对于用Windows的同学，我建议你们直接用WAMP，不过具体配置我倒是没有实际操作过，所以不做任何评论。

关于Yii2

MVC的支持就基本不用多说了，之前发过一篇文章粗略地说过一遍。而在这里我想说明的是：在Yii2中，我们的单入口文件是web/index.php，所以刚刚在开启PHP内置服务器的时候需要来到这个目录，不过如果你直接指定也是可以的。这个文件负责将Yii2项目所需要的东西全部加载完成之后，最后通过run方法来使得整个项目可以跑起来：

      <?php

// comment out the following two lines when deployed to production
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'dev');

require(__DIR__ . '/../vendor/autoload.php');
require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');

$config = require(__DIR__ . '/../config/web.php');

(new yii\web\Application($config))->run();

默认的情况下，我们看到的Yii2首页是/controllers/SiteController.php下的Index方法：

      public function actionIndex()
    {
        return $this->render('index');
    }

通常情况下，控制器一般都会有比较多的方法来链接模型和视图之间的桥梁，但是方法虽多，很多时候都只是一些简单的代码和逻辑，所以，不用担心。

上面的Index方法渲染了index这个模版，而这个模板位于/views/site/index.php，至于控制器和视图之间的命名规则，参考这里：

      views/ControllerID/ViewName.php

ControllerID : 表示控制器的ID，也就是控制器去掉Controller的前缀，比如SiteController就对应site

ViewName : 是对应方法的名字，但是不包括action字眼，比如actionIndex对应的是index.php

而在使用render方法来渲染视图的时候，Yii2默认地也会渲染载入/views/layouts/main.php这个文件，而这个文件做的事就是载入一些html头部的共用文件，比如js，css，导航栏和底部繁荣导航栏等。这里其实我们最值得关心的其实就是下面这段代码的<?= $content ?>：

      <?= Breadcrumbs::widget([
                'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [],
            ]) ?>
            <?= $content ?>
        </div>

这个<?= $content ?>可以说就是我们之后定义视图的内容，我们后续创建的视图文件会被读成字符串的形式赋给$content，然后进行渲染显示。

Hello World

有了上面的安装和基本知识之后，我们就可以自己动手来创建一个页面了。不过在创建页面之前，我们先来做一点简单的配置：开启Yii2的enablePrettyUrl模式，因为这样对于后续的开发会便捷很多，而且开启之后，我们的url也会变得很简洁又好，不想现在这样：

      http://localhost:8999/index.php?r=site%2Fabout

这是我点击首页导航栏的About出现的url，一看到这个，我是拒绝的，所以来到/config/web.php这个配置文件中，找到'components' => []这个数组，加入下面的两行代码：

      'urlManager' => [
            'showScriptName' => false,
            'enablePrettyUrl' => true
        ],

加入之后，正确的代码配置是长成这个样子的：

      'components' => [
        'urlManager' => [
            'showScriptName' => false,
            'enablePrettyUrl' => true
        ],
        'request' => [

这样开启enablePrettyUrl模式之后，我们就可以通过http://localhost:8999/site/about来访问我们的About页面了，这里的规律是这样的：

      http://localhost:8999/ControllerID/ActionName

比如，我们在/controllers/SiteController.php创建一个Say操作方法：

      public function actionSay($target = 'World')
{
    return $this->render('say', ['target' => $target]);
}

我们要访问这个方法的正确路径就是http://localhost:8999/site/say 。

在Yii中使用action关键字前缀来区分用于url操作方法和其他方法，这里的actionSay接收一个参数$target，如果用户在访问的时候传入target参数，target就为用户传入的值，而如果用户没有传入，我们将其默认值设为World。有了控制器的方法，从$this->render('say', ['target' => $target])这行代码来看，我们需要需要创建一个say.php模板文件，这个文件是在哪里的呢？

根据前面说的视图模板规则，它应该位于：/views/site/say.php。在里面简单写上下面这一小段代码：

      <?php
use yii\helpers\Html;
?>
<h1>Hello <?= Html::encode($target) ?></h1>
<p>Welcome to your Yii2 demonstration application.</p>

出于安全的因素考虑，我们在say.php这个模版文件中使用了yii\helpers\Html类来对用户传入的数据进行过滤，所以我们才有了这样的输出：

      <?= Html::encode($target) ?>

我们来访问http://localhost:8999/site/say试试，不出意外这时你看到的是这样的：

然后我们再来访问 ： `http://localhost:8999/site/say?target=少年，还是用Yii吧

虽然说在这里演示用中文不太和谐，但是没办法，我得安利一下各位少年，上手Yii2吧。

第一篇先写到这里了吧，下一篇打算再说说Yii2的MVC,Fomrs 和Layouts这几个知识点。

Happy Hacking

源码会放在Github：https://github.com/JellyBool/helloYii

原文出处：https://jellybool.com/post/programming-with-yii2-exploring-mvc-forms-and-layouts

上一篇文章我们简单地实现了Yii2框架安装和Hello World，而在这一篇文章当中，我们会带着好奇之心去探索一下在Yii2中的几个重要的元素组成：MVC，Forms和Layouts。

本文的目标是创建一个小小的表单应用，就是实现一个简单的类似发微博的功能，但是我还不想牵扯到数据库那一块，因为其实数据库和表在Yii2框架之中其实还是有很多东西可以讲的，打算在下一篇的文章中会详细讲到。

MVC

模型(Model)对于我个人的简单理解就是一个概念集合，在这个集合里面包含该概念集合的多种数据，比如一个User会有姓名，性别等多个属性，这个概念集合通常就是对于数据库的一张表（如果还没有对应的数据表，则可以看作是一个集合的属性）；而每一个具体的实例概念就对应一条数据记录。比如在这一篇文章之中我们会创建一个Status模型，代表状态（来源于生活：发一条状态），这个Status会有两个重要的属性，text和permissions，text就是状态本身，permissions是状态的权限。

视图(Views)通过控制器想模型请求数据，并将数据以某种特定的版式展示给用户。

控制器(Controller)可以向Model和Views发送不同的指令，一般是向Model取数据，然后读取视图文件来渲染输出数据。

在Yii2的应用中，一般是这样的：某个URL指向某个控制器的特定action，然后控制器负责向特定的模型取数据，然后将数据分配给视图渲染输出。

在这里说一下我个人的观点，我觉得其实在MVC当中，可能应该做事最多的应该是Model，与之相迎合的是，Controller和Views则相对要轻一些，Controller负责协调Model和Views，Views负责展示数据。

在Yii2的项目当中，我们将models文件放在/models/目录之下，所以我们在这个文件夹之下创建Status.php：

      <?php

namespace app\models;

use yii\base\Model;

class Status extends Model
{
    const PERMISSIONS_PRIVATE = 10;
    const PERMISSIONS_PUBLIC = 20;

    public $text;
    public $permissions;

    public function rules()
    {
        return [
            [['text','permissions'], 'required'],
        ];
    }

    public function getPermissions() {
      return array (self::PERMISSIONS_PRIVATE=>'Private',self::PERMISSIONS_PUBLIC=>'Public');
    }

    public function getPermissionsLabel($permissions) {
      if ($permissions==self::PERMISSIONS_PUBLIC) {
        return 'Public';
      } else {
        return 'Private';
      }
    }
}

这里需要注意的是rules()这个方法，它会触发Yii自带的表单验证规则，比如这里就是text和permissions这两个表单输入框都不能为空，至于getPermissions()这个方法是为了在使用dropdown输入框的时候使用的。

Status模型创建好之后，我们就可以接着创建对应的控制器和方法。在平时的开发中我习惯是为每一个模型都创建一个对应的控制器，里面一般都是包含几个最常见的方法：index, create, store, update, delete等。这里我创建一个StatusController.php，这个文件应该是位于/controllers/文件夹当中，而我们希望实现一个发表状态的功能，我们必须需要一个create操作方法，比如我们的目的是：在用户访问http://localhost:8999/status/create的时候，我们可以展示创建一条状态的页面给用户。

      <?php

namespace app\controllers;

use Yii;
use yii\web\Controller;
use app\models\Status;

class StatusController extends Controller
{
    public function actionCreate()
    {
        $model = new Status;

        if ($model->load(Yii::$app->request->post()) && $model->validate()) {
            //  $model 有post数据时直接展示
            return $this->render('view', ['model' => $model]);
        } else {
            // 没有数据的时候，直接渲染create视图
            return $this->render('create', ['model' => $model]);
        }
    }
}

首先，根据URL的规则，我们创建了一个actionCreate()方法，在这个方法里，我们通过条件判断来确定展示某个特定的视图。

创建好控制器和方法之后，我们就可以走到下一步了：创建视图。在Yii2中，视图文件的存放位置跟控制器的名字是息息相关的，比如上面我们创建了一个StatusController，我们现在首先需要在views/创建一个status/文件夹，然后在这个文件夹里创建各个跟StatusController相关的视图文件，比如上面actionCreate()中return $this->render()两个视图：view.php和create.php

Forms

首先，我们需要一个Create视图来展示我们创建Status的表单(create.php):

      <?php
  use yii\helpers\Html;
  use yii\widgets\ActiveForm;
  use app\models\Status;
?>
<?php $form = ActiveForm::begin();?>
    <?= $form->field($model, 'text')->textArea(['rows' => '4'])->label('Status Update'); ?>

    <?=
    $form->field($model, 'permissions')->dropDownList($model->getPermissions(),
             ['prompt'=>'- Choose Your Permissions -']) ?>

    <div class="form-group">
        <?= Html::submitButton('Submit', ['class' => 'btn btn-primary']) ?>
    </div>

<?php ActiveForm::end(); ?>

在我们平时开发web应用的时候，表单几乎总是每时每刻都得存在，只要是需要收集信息的地方就需要表单。而Yii2在对表单支持这方面做得非常不错，就如你看到的一样，上面的Yii2 ActiveForm就是Yii2内置的用来帮助我们生成表单的小组件，这里需要注意的是dropDownList这个输入框式怎么实现的，它直接使用了getPermissions()，这个方法正好返回了一个我们需要的数组。

这时候访问：http://localhost:8999/status/create 就可以看到上面创建的表单了：

至于为什么就自动排版好了，不用我们写css，那是因为Yii2默认会给我们加载Bootstrap的css文件，所以我们在使用的时候直接指定类名就OK了。而且很明显地，我们可以看到，一旦输入框在失去焦点的时候，如果里面没有输入任何内容，每个输入框就会有相应的错误提示，用户体验很不错。这个其实是得益于我们在Status模型中声明的rules()方法，Yii2会根据指定的规则通过js在前端给出相应的验证。

然后我们尝试填入一些内容，你就会看到输入框的变化了：

点击Submit 按钮，表单会提交到StatusController的actionCreate()方法，一旦有post数据传过来，就会渲染view.php视图：

到这里，其实我们就走通整个MVC的过程，并且在这个过程中，我们顺带说了一下Forms的知识点。

Layouts

为什么要说Layouts呢？因为Layouts在Yii中其实可以看作是视图中经常重复用到的部分，比如一个HTML文件的header，navigation bar 和footer等，这些都是几乎是在每一个视图文件中都会用到，所以Yii采取了一种一劳永逸的方法来管理这些共用的部分：Layouts就应运而生。这样你就不用在每一个view文件中重复不必要的代码了，而且又特别好管理。

Yii允许你创建多个Layouts，不过我貌似还没遇到那样的使用场景，所以还是无法给出有实证的说法，不管怎么说，一个Layouts就基本够用了。

最后，我们借着Layouts的东风来看看我们怎么修改一下Yii2的默认导航栏：添加一个新的导航。

在上一节我就提到过views\layouts\main.php这个文件，里面的具体结构你可以直打开来看看，我们这里改动的是Nav::widget这部分：

        echo Nav::widget([
                'options' => ['class' => 'navbar-nav navbar-right'],
                'items' => [
                    ['label' => 'Home', 'url' => ['/site/index']],
                    [
                        'label' => 'Status',
                        'items' => [
                            ['label' => 'Create', 'url' => ['/status/create']],
                        ],
                    ],
                    ['label' => 'About', 'url' => ['/site/about']],
                    ['label' => 'Contact', 'url' => ['/site/contact']],
                    Yii::$app->user->isGuest ?
                        ['label' => 'Login', 'url' => ['/site/login']] :
                        ['label' => 'Logout (' . Yii::$app->user->identity->username . ')',
                            'url' => ['/site/logout'],
                            'linkOptions' => ['data-method' => 'post']],
                ],
            ]);

我们在本来的基础之上添加了下面这个内容：

       [
    'label' => 'Status',
    'items' => [
        ['label' => 'Create', 'url' => ['/status/create']],
    ],
],

这样之后，刷新一下页面，你就可以看到我们的导航变化了。而且很神奇的是：这里还实现了dropdown menu的功能，这个其实就是使用Bootstrap的dropdown menu来实现的。

嗯，这篇文章貌似讲得差不多了，至少我不知道还改讲些什么了，接下来的文章我会尝试讲讲Yii2的数据库相关的内容，先睡觉。

原文出处：https://jellybool.com/post/programming-with-yii2-working-with-the-database-and-gii

上一篇文章我们理了一下Yii2的MVC，Forms和Layouts，这篇文章就直接按照约定来说说Yii2与数据库相关的一些事情，如果你觉得不够的话，不急，更具体的用法我会在后续的教程给出，并且这里也会介绍Yii2的代码生成工具：强大的Gii。

你可以直接到Github下载项目源码：https://github.com/JellyBool/helloYii，这样你就可以直接跟上我的进度了，每一次我写完一个教程，我都会将代码push到Github，所以，你想偷懒的话，这是一个不错的方法。

接着上一篇文章，我们的初衷还是没有改变：创建一个可以发表状态(status)的web小应用，你可以看成是QQ空间的说说的mini版，只不过之前我们没有将数据存在数据库里面而已。

创建一个数据库

由于我平时开发基本都是使用Mysql，而且数据库管理工具我比较喜欢Sequel Pro，所以，我就直接在Sequel Pro里面创建一个hello的数据库。当然，你也可以直接用命令行来创建数据库，大概是这样的：

      CREATE DATABASE hello;

有了数据库之后，我们就可以将我们的Yii应用与数据库进行连接了，Yii2的数据库配置文件位于/config/db.php中，我们可以打开它来进行相应的配置，请注意根据自己的实际情况进行相应的修改：

      <?php

return [
    'class' => 'yii\db\Connection',
    'dsn' => 'mysql:host=localhost;dbname=hello',
    'username' => 'root',
    'password' => 'password',
    'charset' => 'utf8',
];

创建Migration

这里直接使用了migration这个单词，其实我不知道该翻译成什么才比较确切；所以本文就直接使用migration这个单词了，如果你知道有特别贴切的翻译，请大声对我说。其实migration的最大目的可能就是创建数据表了，但是我们为什么还要使用migration了？这可能都是受到Rails大法的影响，因为这样的好处其实很多，migration不仅可以让开发人员动态创建和更新一个数据库表的schema，还可以应对多个服务器的时候环境不同的问题，直接就避免导入sql文件的各种坑。

至于在代码中我们该怎么命名我们的数据表，我比较喜欢的是直接跟Model一样，如果是单复数问题也无所谓，这看个人，所以这里，我会选择创建一个status表，iTerm命令行执行：

      cd Desktop/helloYii/

./yii migrate/create create_status_table

过程当中会询问是否创建migration，果断yes，然后完成之后大概是这样的：

这条命令会在项目目录下创建一个migrations/目录，里面就有刚刚我们创建的migration文件，名字大概是这样的：m150804_035107_create_status_table.php，然后我们就可以打开这个文件来一睹芳容了：

      <?php

use yii\db\Schema;
use yii\db\Migration;

class m150804_035107_create_status_table extends Migration
{
    public function up()
    {

    }

    public function down()
    {
        echo "m150804_035107_create_status_table cannot be reverted.\n";

        return false;
    }

嗯，大概就是这样，up()方法是我们后面执行./yii migrate/up命令的时候触发的，这里一般都是负责创建一个表，我们可以将表的schema写在这个方法里面。

创建status表

有了上面的migration之后，我们可以直接在up()方法写上一些我们的字段和配置：

      public function up()
    {
          $tableOptions = null;
          if ($this->db->driverName === 'mysql') {
              $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB';
          }

          $this->createTable('{{%status}}', [
              'id' => Schema::TYPE_PK,
              'message' => Schema::TYPE_TEXT.' NOT NULL DEFAULT ""',
              'permissions' => Schema::TYPE_SMALLINT . ' NOT NULL DEFAULT 0',
              'created_at' => Schema::TYPE_INTEGER . ' NOT NULL',
              'updated_at' => Schema::TYPE_INTEGER . ' NOT NULL',
          ], $tableOptions);
      }

    public function down()
    {
      $this->dropTable('{{%status}}');
    }

这里我们的status会有5个字段，id为主键，message和permissions就是上一篇我们的文本输入框输入的文本内容和下拉选择框的内容；这里我们还要两个created_at和updated_at字段，呃，你可以说我被Laravel洗脑了。

down()方法与up()相对应，用来删除数据表的，我希望你不会用到。

更多详细内容参考这里：

http://www.yiiframework.com/doc-2.0/guide-db-migrations.html

有了表的schema之后，我们就可以来执行我们的migrate命令了，命令行执行：

          ./yii migrate/up

过程中还是果断yes，然后完成之后你就可以到到hello数据库去看status表了：

这里你还会看到一个migration的表，这是Yii2的migrate自动生成了，它是用来管理我们自己创建的migration(这里指数据表)，你可以不用关心它。

使用Yii2的migrate创建完数据表之后，我们下一步就来上手一下Yii2的代码生成工具Gii了，因为我们会通过Gii来生成我们的Model和Controller等文件。

使用Gii

Gii作为Yii的一大特性，很多人喜欢Yii可能就是因为这个，据说底层代码写得很棒，不过我还没有仔细看过源码。

首先我们来使用Gii来为每一个数据表生成一个Model，这里也就是生成Status这个模型。

怎么进入Gii的使用面板呢？直接在浏览器地址栏输入http://localhost:8999/gii 访问就可以了。大概是长这个样子：

点击Model Generator的按钮，然后在Table Name输入框填入表名：status

点击下方Preview 按钮，就可以看到Yii即将帮你生成的文件了models/Status.php，这里需要注意的一个地方是。因为在上一篇文章中我们手动创建了一个Status模型，所以这里请确定你将Overwrite这个选择框的小勾勾打上：

然后点击Generate按钮，生成的结果是这样的：

这时候打开models/Status.php，你会看到Yii会根据我们的数据表生成的验证规则和表单属性：

      <?php

namespace app\models;

use Yii;

/**
 * This is the model class for table "status".
 *
 * @property integer $id
 * @property string $message
 * @property integer $permissions
 * @property integer $created_at
 * @property integer $updated_at
 */
class Status extends \yii\db\ActiveRecord
{
    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return 'status';
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['message', 'created_at', 'updated_at'], 'required'],
            [['message'], 'string'],
            [['permissions', 'created_at', 'updated_at'], 'integer']
        ];
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels()
    {
        return [
            'id' => 'ID',
            'message' => 'Message',
            'permissions' => 'Permissions',
            'created_at' => 'Created At',
            'updated_at' => 'Updated At',
        ];
    }
}

Status模型生成好之后，该为它生成相应的视图和控制器了，这时候需要使用到的是Gii 的CRUD Generator了，即：http://localhost:8999/gii/crud

在这个页面，分别填上对应的数据：

      Model Class : app\models\Status

Search Model Class : app\models\StatusSearch

Controller Class : app\controllers\StatusController

View Path : 可以直接留空，默认就是 app/views/ControllerID

然后点击Preview预览一下，这里还是需要把overwrite勾选上，因为我们上一节也创建了两个同名的视图文件(create.php 和 view.php)：

最后还是点击生成，你会看到类似下面这个图片的内容：

到了这里，我们基本上可以感觉到Gii的强大了，生成代码简直都不算事。这时候如果我们访问http://localhost:8999/status ，你会看到一个默认的Status的CRUD页面，因为我们的数据库里面还没有任何数据，所以这里看到的都是空的：

如果你还记得我们在上一篇在导航栏创建的create导航，点击create，你就会看到类似下面这个页面一样的内容：

到这里，有没有觉得Gii实在太厉害了！要是上一篇我们直接用Gii来生成这些代码，那开发效率实在不是一般高。

与上一篇的结合

虽然Gii足够强大为我们生成了很多代码，但是现在有一小部分代码并不符合我们的要求，我们不用这么复杂。所以下面先来把代码先过过，以便用于满足我们自己的要求。

首先是对创建Status的表单进行改造，我们并不希望用户需要输入created 和updated这两个字段，所以注释掉/views/Status/_form.php中的下面的代码：

      <?= $form->field($model, 'created_at')->textInput() ?>

<?= $form->field($model, 'updated_at')->textInput() ?>

然后permissions字段输入我们希望这是一个下拉选择框，还是在同一个文件中修改：

      <?=
    $form->field($model, 'permissions')->dropDownList($model->getPermissions(),
             ['prompt'=>'- Choose Your Permissions -']) ?>

我们把原来permissions的textInput换成了上面的dropDownList，这里的dropDownList使用到getPermissions()这个方法，但是由于刚刚在生成Status这个模型的时候我们覆盖了原谅的Status，所以我们还是需要加上getPermissions()这个方法：

      const PERMISSIONS_PRIVATE = 10;
const PERMISSIONS_PUBLIC = 20;

// other codes ...

public function getPermissions() {
      return array (self::PERMISSIONS_PRIVATE=>'Private',self::PERMISSIONS_PUBLIC=>'Public');
    }

    public function getPermissionsLabel($permissions) {
      if ($permissions==self::PERMISSIONS_PUBLIC) {
        return 'Public';
      } else {
        return 'Private';
      }
    }

像上一篇提到的一样，我们将这些代码又写到了Status.php这里。然后刷新一下：http://localhost:8999/status/create

到这里，我们的表单改造旧完成了，跟我们之前的长得差不多了。但是这还没有完，因为我们还需要对我们的controllers/StatusController.php做一些些小改动，主要是在actionCreate的改动：

      public function actionCreate()
    {
        $model = new Status();

        if ($model->load(Yii::$app->request->post())) {
          $model->created_at = time();
          $model->updated_at = time();
           if ($model->save()) {
             return $this->redirect(['view', 'id' => $model->id]);
           }
        }
        return $this->render('create', [
            'model' => $model,
        ]);
    }

在这里，我们添加下面这两行来保障我们在插入数据的时候，created_at和updated_at不为空。

      $model->created_at = time();
$model->updated_at = time();

这里也是根据$model->load(Yii::$app->request->post())判断是否有post数据过来，然后如果数据成功保存到数据库，我们就使用return $this->redirect(['view', 'id' => $model->id])重定向到view方法(controllers/StatusController.php的actionView方法)。我们填上一些数据，然后创建一个status试试，不出意外你会看到这个可爱的页面：

终于到了这里了，我们现在再来修改一下我们的导航，在Status这个下来菜单下，我们增加一个菜单view，修改views/layouts/main.php文件的Nav::widget部分：

      [
    'label' => 'Status',
    'items' => [
        ['label' => 'View', 'url' => ['/status/index']],
        ['label' => 'Create', 'url' => ['/status/create']],
    ],
],

就直接在Status的items里面加一行：['label' => 'View', 'url' => ['/status/index']]，然后我们的导航栏就是这样的了：

点击下拉菜单的View，然后我们就会来到：http://localhost:8999/status/index，这里我们可以看到下面的页面了：

这个视图文件位于views/status/index.php，如果你想修改一下，你可以直接修改这个文件。

啊，感觉这一篇文章的路走得好长，不过其实真正编码的时间并不过，真正可能也就几分钟而已，我们实现了对数据库的一些基本操作和领略Gii的强大。这一篇就先写到这里了，下一篇打算会写一点关于用户注册和登录的基本功能。

原文出处：https://jellybool.com/post/programming-with-yii2-integrating-user-registration

本来打算昨晚写的这篇教程，但是忙着约会去了，所以现在补上吧。

上一篇写了一点点Yii2的数据库相关知识和强大的Gii，这一篇就如上一篇的最后所说的一样：在Yii2中实现用户的注册和登录。

你可以直接到Github下载源码，以便可以跟上进度，你也可以重头开始，一步一步按照这个教程来做。本期的用户注册和登录，我会使用一个很棒的composer package ：dektrium/yii2-user，下面就开始我们的故事吧。

用户的注册和登录

在现在的Web应用中，几乎每一个应用都会需要用户注册，不管是使用的第三方还是自建的注册登录系统，我们都需要通过某些表单来收集一些必要的用户数据。这些功能在Yii2之中实现起来并不难，而且有很多种方法，好像很多方法都是比较直接，简单粗暴。这可能是很多人喜欢Yii的原因，就像很多人喜欢PHP一样，就是简单粗暴！

其实在Yii2中，它本身就自带了一个登录的实现:

但是我们重复去制造这个轮子是因为我们需要一些更加实用性的改善，比如：在注册的时候，发送验证邮箱。这几乎是每一个Web应用在注册的时候都会考虑的内容。

如果你安装的是Yii2 Advanced Application Template，那么Yii2其实就把这些功能都写好了，而且你还会有一个后台管理的模块。但是我们的教程是基于Yii2's Basic Application Template，而且我提倡大家来动手造一下这个轮子。

带上我们的作案工具，我们要来造轮子了。

安装Yii2-User

我们这里的Yii2-User安装步骤参照Yii2-User的官方安装文档。我们直接使用composer来进行安装：

      composer require "dektrium/yii2-user:0.9.*@dev"

稍微等待一下，安装完毕之后就可以进行对应的配置了，我们需要配置的文件是config/web.php，找到components，然后在与它同级的位置增加一个modules：

      'components' => [
        // other settings...
    ],
'modules' => [
        'user' => [
            'class' => 'dektrium\user\Module',
            'confirmWithin' => 21600,
            'cost' => 12,
            'admins' => ['admin']
        ],
    ],

这里还需要将components下面的user部分注释掉，不然就会一直登录不了：

       /* 'user' => [
            'identityClass' => 'app\models\User',
            'enableAutoLogin' => true,
        ],*/

还有最后一步就是执行Yii2-User的migration了，在helloYii/目录下执行：

      php yii migrate/up --migrationPath=@vendor/dektrium/yii2-user/migrations

然后你会看到：

果断yes

Bang，到这里Yii2-User安装和配置已经完成了。

配置SwiftMailer

安装完Yii2-User之后我们先不急着去想怎么实现登录和注册(其实很是比较简单的)，我们之前说过的目标是实现用户在注册时候发送验证邮件的，这里我们先来配置一下我们的邮箱服务，因为Yii2-User可以直接使用邮箱来进行注册验证和密码找回等功能。在config/web.php找到mailer这个部分：

      'mailer' => [
    'class' => 'yii\swiftmailer\Mailer',
    // send all mails to a file by default. You have to set
    // 'useFileTransport' to false and configure a transport
    // for the mailer to send real emails.
    'useFileTransport' => true,
],

修改成我们下面的这个样子：

      'mailer' => [
        'class' => 'yii\swiftmailer\Mailer',
        'viewPath' => '@app/mailer',
        'useFileTransport' => false,
        'transport' => [
            'class' => 'Swift_SmtpTransport',
            'host' => 'smtp.live.com',
            'username' => 'jellybool@outlook.com',
            'password' => 'your-password',
            'port' => '587',
            'encryption' => 'tls',
            ],
    ],

这里由于我经常使用的是outlook，不要觉得我是奇葩。所以我在这里使用的是outlook的SMTP配置，各位可以根据自己的需要来进行相应的修改。

开始使用Yii2-User

邮箱配置好了之后，我们就可以开始使用Yii2-User了，首先我们来修改一下我们的导航栏，因为我们想实现的就是我们常常看到的在导航栏的右侧的注册和登录按钮。在/views/layouts/main.php找到：

      echo Nav::widget([
            'options' => ['class' => 'navbar-nav navbar-right'],
            'items' => [
                ['label' => 'Home', 'url' => ['/site/index']],
                [
                    'label' => 'Status',
                    'items' => [
                        ['label' => 'View', 'url' => ['/status/index']],
                        ['label' => 'Create', 'url' => ['/status/create']],
                    ],
                ],
                ['label' => 'About', 'url' => ['/site/about']],
                ['label' => 'Contact', 'url' => ['/site/contact']],
                Yii::$app->user->isGuest ?
                    ['label' => 'Login', 'url' => ['/site/login']] :
                    ['label' => 'Logout (' . Yii::$app->user->identity->username . ')',
                        'url' => ['/site/logout'],
                        'linkOptions' => ['data-method' => 'post']],
            ],
        ]);

上面的启示就是我们在上一篇文章修改过后的导航栏的代码，然后用下面的代码进行替换：

      $navItems=[
    ['label' => 'Home', 'url' => ['/site/index']],
    ['label' => 'Status', 'url' => ['/status/index']],
    ['label' => 'About', 'url' => ['/site/about']],
    ['label' => 'Contact', 'url' => ['/site/contact']]
  ];
  if (Yii::$app->user->isGuest) {
    array_push($navItems,['label' => 'Sign In', 'url' => ['/user/login']],['label' => 'Sign Up', 'url' => ['/user/register']]);
  } else {
    array_push($navItems,['label' => 'Logout (' . Yii::$app->user->identity->username . ')',
        'url' => ['/site/logout'],
        'linkOptions' => ['data-method' => 'post']]
    );
  }
echo Nav::widget([
    'options' => ['class' => 'navbar-nav navbar-right'],
    'items' => $navItems,
]);

修改完成之后，我们直接访问：http://localhost:8999/user/register，你将会看到下面的类似页面：

有没有觉得很神奇？没错Yii2-User帮我们都全部写好了！然后我们输入相应的信息点击注册，之后就会看到这个信息提示页面：

提示新说表明验证邮箱已经发送，我们登录qq邮箱去看看，果然：

看到这个，相信大家都会很开心，有图有真相。直接点击邮件的验证链接，然后就会看到Yii2-User给我们反馈的验证成功的信息：

注意右上角，这个时候我们已经登录到应用了，如果点击Logout就会回到登录页面：

到这里，注册登录整个流程就实现完了，不过还有一个我们日常开发经常遇到的情况：忘记密码。嗯，对于这个情况，Yii2-User直接就提供了这个功能！你可以直接访问：http://localhost:8999/user/forgot 就可以看到了：

嗯，就这样，很简单吧。借助Yii2-User这个强大的composer package，我们可以轻松实现用户注册，登录和忘记密码等各个功能。当然，Yii2-User还有很多特性，我们这里只是用到了很小一部分，你可以直接到文档中查看：

https://github.com/dektrium/yii2-user/blob/master/docs/README.md

最后希望这一篇文章可以帮你解决一些问题。下一步我肯能会说一下用户权限控制和管理，因为这里实现的用户注册，所以下一篇显得是自然而然的。

原文出处：https://jellybool.com/post/programming-with-yii2-user-access-controls

上一篇文章讲了用户的注册，验证和登录，这一篇文章按照约定来说说Yii2之中的用户和权限控制。

你可以直接到Github下载源码，以便可以跟上进度，你也可以重头开始，一步一步按照这个教程来做。

鉴于本教材基于Yii2 Basic，所以对RBAC的详细讲解我后面再单独出文章来说说吧，这里主要是简单地说一说权限控制

上一篇文章所实现的功能还比较简单，可以发一条状态，但是不知道你注意到没有，如果是没有注册的用户也可以使用我们的应用(类似小微博)来发状态，这是不符合情理的。正确的做法是在用户没有注册，登录之前，我们甚至都不应该给没有注册的用户看到我们创建状态的页面，即是http://localhost:8999/status/create就不应该让游客看到，更不用说编辑和删除一条状态(status)了。

权限控制

什么是权限控制？个人觉得在一个Web应用当中，有以下几种常见的角色和权限控制：

      1. 游客，也就是没有注册的用户，一般这个权限是最小的，对于一些需要登录访问的页面没有访问权限

2. 用户，这里的用户特指注册用户，注册过后的用户一般可以使用整个web应用的主要功能，比如我们这里的发表一条状态(status)

3. 作者，这个不知道确切应该使用什么名词来描述，作者是在用户注册之后的一个权限判断，比如A发表的status状态，B君不能进行编辑，删除等，反之亦然。

4. 管理员，这里的管理员通常会是应用的开发者(所有者，或者应该这么说)，几乎可以说是对站点的所有权限都有

Yii2自带的权限控制默认只支持两个角色：

guest(游客，没有登录的，用?表示)

authenticated (登录了的，用@表示)

在这里我们需要实现的是对这两种不同的角色指定不同的访问权限，就是为他们分配不同的可以访问的控制器或者方法。

目前我们如果直接点击导航栏的Status，我们还是可以在没有登录的情况之下进行发表状态(status)，所以我们需要改一下我们的代码和逻辑，Yii2在这方面的控制做得非常好，其实实现这个我们只需要修改一下StatusController.php里面的behaviors()方法而已，在这里面加入一段access设置：

      public function behaviors()
    {
        return [
            'verbs' => [
                'class' => VerbFilter::className(),
                'actions' => [
                    'delete' => ['post'],
                ],
            ],
            'access' => [
                'class' => AccessControl::className(),
                'only' => ['index','create','update','view'],
                'rules' => [
                    // allow authenticated users
                    [
                        'allow' => true,
                        'roles' => ['@'],
                    ],
                    // everything else is denied
                ],
            ],
        ];
    }

加上access这一段之后，我们再次点击Status，Yii2就会将未登录的我重定向到登录页面。

而且，这个时候，一旦你登入进去，Yii会默认自动跳转到上一个url，也就是我们刚刚点击的status/index。

添加映射关系

用户一旦登录进来之后，我们就可以通过下面这行代码来获取用户的id了：

      Yii::$app->user->getId();

一旦用户的id获取到，我们可以做的事就很多了。这里我们先来将一条状态和用户联系起来，也就是添加用户与说说的映射关系。要实现这个目标我们需要先修改我们的数据表(体验一下当初设计数据表考虑不周全的情况)：

      ./yii migrate/create extend_status_table_for_created_by
Yii Migration Tool (based on Yii v2.0.6)

Create new migration '/Users/jellybool/Desktop/helloYii/migrations/m150806_034325_extend_status_table_for_created_by.php'? (yes|no) [no]:yes

New migration created successfully.

打开对应的migration文件，编辑up()和down()方法，如果你想加入数据库的事务管理功能，你可以使用safeUp()和safeDown()方法

      public function up()
    {
        $this->addColumn('{{%status}}','created_by',Schema::TYPE_INTEGER.' NOT NULL');
        $this->addForeignKey('fk_status_created_by', '{{%status}}', 'created_by', '{{%user}}', 'id', 'CASCADE', 'CASCADE');
    }

public function down()
{
    $this->dropForeignKey('fk_status_created_by','{{%status}}');
    $this->dropColumn('{{%status}}','created_by');
}

我们需要为status表添加一个created_by字段，并且将它跟user表的id设为外键关系。

如果你在status表里面有一条数据记录，你需要先删除这一条记录，不然可能会报错。

执行migrate/up:

      ./yii migrate/up
Yii Migration Tool (based on Yii v2.0.6)

Total 1 new migration to be applied:
    m150806_034325_extend_status_table_for_created_by

Apply the above migration? (yes|no) [no]:yes
*** applying m150806_034325_extend_status_table_for_created_by
    > add column created_by integer NOT NULL to table {{%status}} ... done (time: 0.032s)
    > add foreign key fk_status_created_by: {{%status}} (created_by) references {{%user}} (id) ... done (time: 0.014s)
*** applied m150806_034325_extend_status_table_for_created_by (time: 0.059s)

数据表的外键设置好之后，我们就可以来声明Status和User的关系了，不过在开始之前需要修改一下User.php里面的内容：

      <?php
namespace app\models;

use dektrium\user\models\User as BaseUser;

class User extends BaseUser {

    public function register()
    {

    }
}

直接将原来的User模型的代码都删掉，只需要我们上面的代码就可以了，因为我们使用了Yii2-User， 这里就是使用dektrium\user\models\User这个模型，然后修改一下我们的config/web.php，再我们之前的user中加入几行代码：

       'modules' => [
        'user' => [
            'class' => 'dektrium\user\Module',
            'confirmWithin' => 21600,
            // add the following 3 lines
            'modelMap' => [
                'User' => 'app\models\User',
            ],

            'cost' => 12,
            'admins' => ['admin']
        ],
    ],

这样之后，我们的User和Status的对应关系就会建立起来。

然后我们在Status.php写上以下的说明：

      public function getUser()
    {
        return $this->hasOne(User::className(), ['id' => 'created_by']);
    }

这里声明的映射关系为hasOne，也就是说，一条状态status(说说)对应一个用户(User)，我们通过['id' => 'created_by']来指定外键映射。

有了Status和User的对应关系之后，我们需要在用户发表状态的时候将用户的id保存到Status的created_by这一个字段中，所以我们需要在StatusController中的actionCreate方法中加上一行代码：

      if ($model->load(Yii::$app->request->post())) {
    $model->created_by = Yii::$app->user->getId();//add this line
    $model->created_at = time();
    $model->updated_at = time();
    if ($model->save()) {
        return $this->redirect(['view', 'id' => $model->id]);
    }
}

这里需要确认的是，你需要保证create方法只能是登录进来的用户才能访问触发。

为了更好地展示一条状态stutas的信息，我们修改一下展示状态的视图文件：status/view.php :

      <?= DetailView::widget([
        'model' => $model,
        'attributes' => [
            'id',
            'user.email', // add this line
            'message:ntext',
            'created_by', // add this line
            'permissions',
            'created_at',
            'updated_at',
        ],
    ]) ?>

上面的user.email中的user其实是触发Status::getUser()这个方法。

这样一刷新之后，我们就可以看到创建这条状态的用户id和email了。

探寻RBAC

上面的一些列设置和代码更改，已经实现了一小部分的用户控制：登录的用户才能发表status。然而这还不能满足我们在日常使用的需求，比如我们现在怎么确定一个用户能不能对某条状态进行修改和删除？或者说，管理员的角色在哪里体现呢？现在貌似都是平等的角色，相同的权限，对于登录的用户来说。

鉴于官方文档或者很多关于Yii2 RBAC的资料都是基于Yii2 Advanced Template，而我们一开始使用的是Yii2 Basic Template，并且我们也引入Yii2-User，所以这里我们尝试来自己实现一点点的用户权限控制。

首先我们需要在User中定义一些跟角色(role)相关的规定，比如根据不同的用户角色来赋予不同的常量：

      class User extends BaseUser {
    const ROLE_USER = 10;
    const ROLE_MODERATOR = 20;
    const ROLE_ADMIN = 30;

}

上面的代码写在User模型里面，这里定义了三种角色，ROLE_USER，ROLE_MODERATOR，ROLE_ADMIN，USER可以发表状态，MODERATOR可以修改但是不可以删除，ADMIN可以修改和删除。

然后在helloYii/目录之下创建一个components/目录，里面新建一个AccessRule.php文件：

      <?php

namespace app\components;

use app\models\User;
class AccessRule extends \yii\filters\AccessRule {

    /**
     * @inheritdoc
     */
    protected function matchRole($user)
    {
        if (count($this->roles) === 0) {
            return true;
        }
        foreach ($this->roles as $role) {
            if ($role === '?') {
                if ($user->getIsGuest()) {
                    return true;
                }
            } elseif ($role === User::ROLE_USER) {
                if (!$user->getIsGuest()) {
                    return true;
                }
                // Check if the user is logged in, and the roles match
            } elseif (!$user->getIsGuest() && $role === $user->identity->role) {
                return true;
            }
        }

        return false;
    }
}

这里就直接借用Yii2自带的\yii\filters\AccessRule来控制权限规则。但是由于Yii2-User在创建user数据表的时候并没有role这个字段，所以我们需要手动添加，你可以直接在mysql敲命令行，或者也可以通过数据库管理工具来添加。

最后更新一下我们的StatusController.php文件，这里的behaviors()方法会做出一些调整：

      <?php

namespace app\controllers;

use Yii;
use app\models\Status;
use app\models\StatusSearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use yii\filters\AccessControl;
use app\components\AccessRule;
use app\models\User;

/**
 * StatusController implements the CRUD actions for Status model.
 */
class StatusController extends Controller
{
    public function behaviors()
    {
        return [
            'verbs' => [
                'class' => VerbFilter::className(),
                'actions' => [
                    'delete' => ['post'],
                ],
            ],
            'access' => [
                'class' => AccessControl::className(),
                // We will override the default rule config with the new AccessRule class
                'ruleConfig' => [
                    'class' => AccessRule::className(),
                ],
                'only' => ['index','create', 'update', 'delete'],
                'rules' => [
                    [
                        'actions' => ['index','create'],
                        'allow' => true,
                        // Allow users, moderators and admins to create
                        'roles' => [
                            User::ROLE_USER,
                            User::ROLE_MODERATOR,
                            User::ROLE_ADMIN
                        ],
                    ],
                    [
                        'actions' => ['update'],
                        'allow' => true,
                        // Allow moderators and admins to update
                        'roles' => [
                            User::ROLE_MODERATOR,
                            User::ROLE_ADMIN
                        ],
                    ],
                    [
                        'actions' => ['delete'],
                        'allow' => true,
                        // Allow admins to delete
                        'roles' => [
                            User::ROLE_ADMIN
                        ],
                    ],
                ],
            ],
        ];
    }

我们上面根据不同等级的用户赋予不同的访问权限，这时候，如果你先logout出来，再登录回去，你还是可以看到这些status，但是一旦你点击delete(删除按钮)，你将会看到一个报错的页面：

我们手动创建的role是成功，但是我们怎么给一个注册的用户默认的权限呢，我们这里就是想实现在新用户注册的时候赋予用户ROLE_USER的角色和权限。由于Yii2-User是在vendor\dektrium\yii2-user\models\RegistrationForm.php这个文件里面进行创建新的用户的，我门这里只要修改一个小地方，找到register()方法：

        public function register()
    {
        if ($this->validate()) {
            $user = $this->module->manager->createUser([
                'email'    => $this->email,
                'username' => $this->username,
                'password' => $this->password,
                'role'=>10, // add this line User::ROLE_USER;
            ]);

            return $user->register();
        }

        return false;
    }

添加'role'=>10就可以了。

如果你想证明一下我们的权限是否正确，你可以手动修改数据库中的role字段的数值，然后在进行修改和删除等操作，看看是否可以正确运行。

权限控制其实可以说是Yii2的一大特色和亮点，在这里可能并没有说得很清晰，只是简单地实现了一些规则，有机会借助Yii2 Advanced Template来实现一下。

源码会放在 Github：https://github.com/JellyBool/helloYii

下一节

下一节尝试集成一个编辑器和做一下url的美化，内容应该会比较简单

原文出处：https://jellybool.com/post/programming-with-yii2-rich-text-input-with-redactor

首先，很惭愧的是，前几天都出去外面玩了，没有及时更新教程，实在是太愧疚了，所以回来之后还是好好写完这个系列教程吧。

上一篇文章我们实现了简单的用户权限管理，至于更先进的RBAC，我后面会单独出一篇文章来说说。在这一篇文章当中，我主要想写的是在Yii2中集成一个编辑器，因为在我们的实际开发当中，一个简单的textarea一般都是不能满足我们的需求的，因为我们需要多种多样的文本样式如标题，表格啦，并且很多时候我们在这些文本当中还需要插入图片和视频。而这些问题目前的最好解决方案就是集成一个编辑器，鉴于大家(这里不是指程序员)都是喜欢所见即所得，所以，这里我主要是演示怎么集成所见即所得的富文本编辑器。

Redactor

既然是集成富文本编辑器，我们首先得找一个喜欢并且功能还不错的编辑器，而在我这里，我选择了Redactor这个编辑器，这不仅是因为Redactor有官方的Yii2插件package，它还是一款在保存美观的同时又能给你提供强大功能的编辑器，在我个人的使用体验来说，这个编辑器给我的感受时最好的。

安装 Redactor

既然决定使用Redactor，我们首先要做就是来安装Redactor了，上面说过的，Yii2有官方的插件package，并且还提供了composer的安装方式(我最喜欢这种了)，

可以看看这里：https://github.com/yiidoc/yii2-redactor

所以我们可以通过下面的命令来安装Redactor：

      composer require --prefer-dist yiidoc/yii2-redactor "*"

坐等一会之后，你即将看到下面的类似信息：

        - Installing yiidoc/yii2-redactor (2.0.1)
    Downloading: 100%

Writing lock file
Generating autoload files

在这里可以看到Redactor给Yii2提供的插件目前的最新版是2.0.1。安装完了之后，我们需要进行一些简单的配置，还是像前面的一样，来到config/web.php：

      'modules' => [
        'redactor' => 'yii\redactor\RedactorModule',
        'user' => [
            // here is the config for user
        ],
    ],

我们直接在modules这里加上一行'redactor' => 'yii\redactor\RedactorModule',，这样就可以简单的实现Redactor提供的富文本编辑器功能了。

配置好之后，我们来将我们原先发表状态的textarea替换成Redactor的富文本编辑框，来到我们的views/status/_form.php文件中：

      <div class="status-form">

    <?php $form = ActiveForm::begin(); ?>

    <!--
    <?//= $form->field($model, 'message')->textarea(['rows' => 6]) ?>
    -->
    <?= $form->field($model, 'message')->widget(\yii\redactor\widgets\Redactor::className()) ?>

将原来的$form->field($model, 'message')->textarea(['rows' => 6])注释掉，然后替换成Redactor的文本框配置。

然后我们访问：http://localhost:8999/status/create ，就可以看到类似下面的可爱页面了：

没错，就是这么几行代码，我们就把富文本编辑器集成到我们的应用当中了。我们来试着创建一条状态试试：

由于Redactor提交的是HTML格式的文本(一般富文本编辑器应该也是这样)。所以我们会看到有<p></p>这个标签。

实现图片上传

上面的Redactor配置还不能正确地使用上传图片和管理图片的功能，那么我们这里就来实现一下。首先我们需要在web/目录下创建一个uploads/目录，这是Redactor默认的上传图片的存放目录；然后我们还需要修改一下config/web.php这个文件中的Redactor的配置：

      'modules' => [
        'redactor' => [
            'class' => 'yii\redactor\RedactorModule',
            'imageAllowExtensions'=>['jpg','png','gif']
        ],

我们这里指定了上传图片的类型，演示时只支持jpg，png 和gif这三种，最后在views/status/_form.php中进行相应的设置：

       <?= $form->field($model, 'message')->widget(\yii\redactor\widgets\Redactor::className(),
        [
            'clientOptions' => [
                'imageManagerJson' => ['/redactor/upload/image-json'],
                'imageUpload' => ['/redactor/upload/image'],
                'fileUpload' => ['/redactor/upload/file'],
                'lang' => 'zh_cn',
                'plugins' => ['clips', 'fontcolor','imagemanager']
            ]
        ]
        ) ?>

我们这里加入了一些clientOptions，我这里配置了图片管理和上传，文件上传，显示语言，和一些小插件：字体颜色，字体背景色等。图片和文件的上传都是用的官方默认的上传配置，更多的配置和文档，你可以看看这里：

https://github.com/yiidoc/yii2-redactor

tips: 时常关注Github上的文档更新呗

然后我们再来访问一下： http://localhost:8999/status/create ，试着上传一张图片试试：

这张图片是本人前几天去凤凰浪的时候拿手机拍的，然后我们点击发表，又可以看到我们的status的内容了，不过这里还是HTML格式的文本。

最后可以查看一下你的web/uploads/目录，看看图片是不是正确上传了。关于更多的上传图片和文件的安全配置信息，你可以看看这篇文章：

How to Setup Secure Media Uploads

一路写下来，真的是觉得Redactor非常顺手，所以我还是很推荐大家在Yii2的项目中集成这个富文本编辑器，因为颜值和功能都很是awesome!

下一节

我们的基本流程全部实现之后，下一节之后的教程，我会更注重讲解Yii2的一些特性如：Behaviors Validations等。