Yii2的相關學習記錄,先後臺分離及migrate使用(七)

最近一直忙其它的(實際上是懶!),將《深刻理解Yii2》看了一遍,一些當初沒明白的稍微明瞭了點,而後又看yii2的圖片上傳等處理、富文本、restful什麼的,但因爲沒進行到這裏,只看也無論用啊,因此仍是按照步驟一步步來,先說說先後臺分離。(其實普通的內容管理站點用不着下面所說的完全分離什麼的,看看也無妨)php

我的感受先後臺的狀況有這麼幾種,首先是先後臺是不是用一個驗證體系,其次是先後臺是否共用一個數據表。通常來講下面三種比較經常使用吧:html

A、共用一個驗證體系和一個數據表。mysql

B、兩個驗證體系和共用一個數據表。linux

C、兩個驗證體系和兩個數據表。web

Yii2高級版裏面默認是A類型,即數據表同樣,且一邊登陸/登出了,另外一邊也一樣登陸/登出,感受這種結構比較適用於論壇這種,管理員也須要有與會員同樣發帖回帖等功能,表字段也基本一致,(我的這樣認爲,畢竟接觸的很少,網上也搜過不一樣的後臺構建的話題,可是不多有詳細討論的),這種能夠經過字段、權限等來區分先後臺。而咱們將要作的是C類型,像是一些電商網站,後臺的管理員和前臺的會員功能就相差太大了,且表字段差異也大,因此驗證體系不同,並且放兩個數據表比較好。至於B類型算是C類型的簡化版,C若是會設置的話,B也同理。sql

那咱們先創建一個admin表,用來存放管理員數據,而會員仍然用原有的user表,這裏用yii的migrate來建立,在Yii2初始化章節中有提到過,這裏稍微詳細說下:數據庫

一、yii2版本2.07之前用命令,便可在console/migrations目錄下建立一個php文件,而後在此文件下編寫建立表語句等等就能夠了。windows

yii migrate/create admin

二、yii2版本2.07後,增長了更細緻的分類,例如我已經建立了admin表,但少了一個status字段,那我能夠直接用下面命令便會生成只增長字段的文件api

yii migrate/create add_column_to_admin --fields=status:int(10):nontNull

生成:restful

<?php
use yii\db\Migration;

class m160501_053640_add_column_to_admin extends Migration
{
    public function up()
    {
        $this->addColumn('admin', 'status', $this->int(10)->nontNull());
    }

    public function down()
    {
        $this->dropColumn('admin', 'status');
    }
}

具體爲何會這樣,咱們看下原代碼,在vendor/yiisoft/yii2/console/BaseMigrateController.php文件的actionCreate方法中:

...
} elseif (preg_match('/^add_(.+)_to_(.+)$/', $name, $matches)) {
    $content = $this->renderFile(Yii::getAlias($this->generatorTemplateFiles['add_column']), [
        'className' => $className,
        'table' => mb_strtolower($matches[2], Yii::$app->charset),
        'fields' => $this->fields
    ]);
}
...

咱們能夠看到,這裏是正則匹配add_xxx_to_xxx來肯定具體是指向哪一個模板,從而生成不一樣的樣式。因此根據migrate/create後面的參數總共匹配這幾種樣式:

一、create_junction_表名_and_表名,用來建立聯結表

二、add_xxx_to_表名,用來增長字段(能夠用--fields樣式指定一個字段,不然生成空的,須要本身寫,固然也能夠改模板添加個註釋示例)

三、drop_xxx_from_表名,用來刪除字段(同上)

四、create_表名,用來建立表

五、drop_表名,用來刪除表

 注:能夠直接在控制檯用yii help migrate來查看更多的用法

2.09版本這裏又有改動,全部的都要以"_table"結尾才能被正確匹配,例如原先是"yii migrate/create create_category",如今必須是"yii migrate/create create_category_table"這樣,這裏說明下,上面就不一一修改了,

模板文件能夠在vendor/yiisoft/yii2/views中找到對應的,若是想更改模板,讓其更適合本身的操做,能夠這樣:

在console文件中新建views文件夾,將上方的你想修改的模板複製到這裏來修改,而後再console/config/main.php中修改

return [
    //修改migration模板
    'controllerMap' => [
        'migrate' => [
            'class' => 'yii\console\controllers\MigrateController',
            'templateFile'=>'@yii/views/migration.php',//默認模板,2.07後應該不多用了
            'generatorTemplateFiles' => [
                'create_table' => '@console/views/createTableMigration.php',//修改的
                'drop_table' => '@yii/views/dropTableMigration.php',//未修改的
                'add_column' => '@console/views/addColumnMigration.php',//修改的
                'drop_column' => '@console/views/dropColumnMigration.php',//修改的
                'create_junction' => '@yii/views/createJunctionMigration.php'//未修改的
            ],
        ],
    ],
];

值得注意的是generatorTemplateFiles配置中,必須將這5個都寫全了,若是不修改,則寫原來的路徑,原來的路徑可在vendor/yiisoft/yii2/console/MigrateController.php中查看,不然你用到沒寫的那個命令模板的時候就會報錯。

至於如何寫具體的建立表、添加字段等語句,其實也有版本不一樣(2.06新寫法)的兩種寫法,這裏就不要看中文版的沒有更新的yii2指南了,直接看英文更新的,點這裏,裏面包含上面說的內容加具體的寫法。當初費了不少時間google搜索、順着源碼看才搞明白上面說的原理,後來一看,在人家英文版裏都寫了,悲劇,並且最近我在Yii英文官網api文檔搜索任何關鍵字都不出現結果了,不知道是這邊的問題仍是官網問題,只能對照着中文指南和英文指南看究竟是對應的哪一塊。因此說若是英語更好點就行了,直接看英文文檔。

目前本身修改了create_table時加表註釋、段註釋(這個搜索及查源碼沒找到相似->comment的寫法,多是爲了兼容其它數據庫,因此只能拼接,而寫段註釋的好處是,gii 生成model時attributeLabels方法能夠直接根據註釋來顯示對應的中文名字),add_column和drop_column模板增長一個示例註釋,方便忘了用法時參照註釋的示例來寫,並且這樣就不用加--fileds參數了。呃,這裏貼一下本身的模板和最終應該創建的admin表的語句吧:

模板createTableMigration.php:

<?php
/**
 * This view is used by console/controllers/MigrateController.php
 * The following variables are available in this view:
 */
/* @var $className string the new migration class name */
/* @var $table string the name table */
/* @var $fields array the fields */

echo "<?php\n";
?>

use yii\db\Migration;

class <?= $className ?> extends Migration
{
    const TBL_NAME = '{{%<?=$table?>}}';
    public function up()
    {
        $tableOptions = null;
        if ($this->db->driverName === 'mysql') {
            $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE=InnoDB COMMENT="填寫表註釋"';
        }
        $this->createTable(self::TBL_NAME, [
<?php foreach ($fields as $field): ?>
<?php if ($field == end($fields)): ?>
            '<?= $field['property'] ?>' => $this-><?= $field['decorators'].".\" COMMENT '填寫段註釋'\"" . "\n"?>
<?php else: ?>
            '<?= $field['property'] ?>' => $this-><?= $field['decorators'].".\" COMMENT '填寫段註釋'\"" . ",\n"?>
<?php endif; ?>
<?php endforeach; ?>
        ],$tableOptions);
    }

    public function down()
    {
        $this->dropTable(self::TBL_NAME);
    }
}
createTableMigration.php

 具體語句m160326_133655_create_admin.php:

<?php

use yii\db\Migration;

class m160427_133556_create_admin extends Migration
{
    const TBL_NAME = '{{%admin}}';
    public function up()
    {
        $tableOptions = null;
        if ($this->db->driverName === 'mysql') {
            $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE=InnoDB COMMENT="後臺管理員表"';
        }
        $this->createTable(self::TBL_NAME, [
             'id' => $this->primaryKey(),
            'username'=>$this->string()->notNull()->unique()." COMMENT '用戶名'",
            'auth_key'=>$this->string(32)->notNull()." COMMENT '認證Key'",
            'password_hash'=>$this->string()->notNull()." COMMENT '密碼'",
            'password_reset_token'=>$this->string()->unique()." COMMENT '密碼重置Token'",
            'email'=>$this->string()->notNull()->unique()." COMMENT '郵箱'",
            'status'=>$this->smallInteger()->notNull()->defaultValue(10)." COMMENT '狀態'",
            'created_at' => $this->integer()->notNull()." COMMENT '建立時間'",
            'updated_at' => $this->integer()->notNull()." COMMENT '更新時間'",
        ],$tableOptions);
    }

    public function down()
    {
        $this->dropTable(self::TBL_NAME);
    }
}
xxx_create_admin.php

繼續運行下述命令行代碼,便可生成admin表,因爲只是作演示,因此admin和user表基本同樣,不要在乎這些細節。

yii migrate

 好了,生成兩個表後,咱們就須要將前臺登陸和後臺登錄完全分開了:

一、前臺修改:因爲已經不公用了,因此先把公用的common/models中的User.php和LoginForm.php移動到frontend/models中去,順便將這兩個文件的命名空間改成以frontend開頭,將整個前臺文件看一遍,把全部涉及到這兩個common文件命名空間的須要都改成前臺本身的命名空間。

二、後臺修改:一樣須要在backend/models中有這兩個文件Admin.php和LoginForm.php,可使用Gii生成(須要注意要繼承IdentityInterface,實現此接口內的方法以及參照User.php來實現相關登陸註冊方法),也能夠直接複製一樣上面的兩個文件(須要將User.php更名爲Admin.php,且注意user表和admin表字段名稱或個數是否一致,不一致則須要在Admin.php中修改)。因爲咱們原先建立事後臺的GRUD,因此這裏改動挺多的(searchModel,controller,view都須要改爲admin的),建議對照着Gii生成的文件預覽來改。哎,若是實際要先後臺分離,本章應該放在第五章節的前面,那後臺就不須要改這麼多了。

如今能夠登陸先後臺試試,等等,咱們後臺表雖然建立好了,可是尚未添加管理員,如今因爲後臺已經登錄不進去了,因此在後臺內也沒法建立了,而且註冊功能也沒有(這種分離下,後臺通常不必有註冊功能),因此這裏繼續用console的功能來建立一個用戶,控制檯的功能挺多的,不只僅是數據庫管理,能夠點這裏瞭解下。

在console/controllers中新建InitController,而後以下代碼:

<?php
/**
 * Application initialization
 * 參照深刻理解Yii2.0視頻教程
 */
namespace console\controllers;

use backend\models\Admin;

class InitController extends \yii\console\Controller
{
    /**
     * Create init admin
     */
    public function actionAdmin()
    {
        echo "Create init admin ...\n";                  // 提示當前操做
        $username = $this->prompt('Admin Name:');        // 接收用戶名
        $email = $this->prompt('Email:');               // 接收Email
        $password = $this->prompt('Password:');         // 接收密碼
        $model = new Admin();                            // 建立一個新用戶
        $model->username = $username;                   // 完成賦值
        $model->email = $email;
        $model->password = $password;//注意這個地方,用了Admin模型中的setPassword方法(魔術方法__set)
        if (!$model->save())                            // 保存新的用戶
        {
            foreach ($model->getErrors() as $error)     // 若是保存失敗,說明有錯誤,那就輸出錯誤信息。
            {
                foreach ($error as $e)
                {
                    echo "$e\n";
                }
            }
            return 1;                                   // 命令行返回1表示有異常
        }
        return 0;                                       // 返回0表示一切OK
    }

}

InitController.php
InitController.php

而後再命令行中運行:

yii init/admin

按照提示來填寫用戶名密碼等,即可以產生一條數據了,當咱們查看這條記錄時,發現咱們填寫的明文密碼變成加密的了,而建立時間和更新和更新時間咱們沒填寫也自動給填寫了,前者是因爲用了__set魔術方法,後者是用了「行爲」,若是不是很理解請看《深刻理解Yii2.0》,裏面講的比較詳細。還有就是,可能在window下cmd運行中文亂碼,大致搜了下沒找到好的解決方法,不過能夠試下Cygwin這個windows下能夠運行linux命令的軟件,挺好用的,設置成utf-8就不會亂碼了,並且能夠用gcc什麼的。

三、如今咱們先後臺都能按照本身數據庫裏的數據來登陸了,可是因爲session等公用一個,因此仍是退出時,先後臺一塊兒退出,須要進一步操做:能夠參照這篇wiki

後臺,在backend/config/main.php或者main-local.php中

'components' => [
    'user' => [
        'identityClass' => 'backend\models\Admin',
        'enableAutoLogin' => true,
        'identityCookie' => [
            'name' => '_backendUser', // unique for backend
        ],
    ],
    'session' => [
        'name' => 'PHPBACKSESSID',
        'savePath' => sys_get_temp_dir(),
    ],
    'request' => [
        'cookieValidationKey' => 'orGkZNZvZe3-4WicYHyGMS-EyI6Tp8yi',//random string
        'csrfParam' => '_backendCSRF',
    ],
...

一樣在前臺,在frontend/config/main.php或者main-local.php中

'components' => [
    'user' => [
        'identityClass' => 'frontend\models\User',
        'enableAutoLogin' => true,
        'identityCookie' => [
            'name' => '_frontendUser', // unique for frontend
        ]
    ],
    'session' => [
        'name' => 'PHPFRONTSESSID',
        'savePath' => sys_get_temp_dir(),
    ],
    'request' => [
        'cookieValidationKey' => '8rqO22WJ9yiAx_KuJ8SFnbKctqGDWi9J',
        'csrfParam' => '_frontendCSRF',
    ],
...

這樣再登錄試下,就會發現先後臺徹底沒關聯了。能夠調用Yii::$app的功能,例如Yii::$app->user->id,若是是在後臺的目錄中,會顯示後臺的用戶id,若是是在前臺的目錄中則會顯示前臺的用戶id。可能有些強迫症患者想同Yii1那樣用Yii::$app->admin->id來訪問後臺用戶id,這個不太好實現,Yii2和Yii1相比,用戶驗證這塊改動挺大的,web/User在Yii2框架中做爲核心組件,若是要修改的話應該還要關聯修改web/Application中的變量方法等,我的感受不必。

以上,就是所說的,其實還有不少已經集成好的yii2-user、帶權限控制等的插件能夠直接從composer中搜索使用。例如點擊率最高的這個,能夠配置B類型的驗證,並且集成了更多功能。(我的只是大致看了下,沒下載使用呢還)

相關文章
相關標籤/搜索