程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> PHP綜合 >> Yii2前後台分離及migrate使用(七)

Yii2前後台分離及migrate使用(七)

編輯:PHP綜合

最近一直忙其它的(其實是懶!),將《深入理解Yii2》看了一遍,一些當初沒明白的稍微明了了點,然後又看yii2的圖片上傳等處理、富文本、restful什麼的,但由於沒進行到這裡,只看也不管用啊,所以還是按照步驟一步步來,先說說前後台分離。(其實普通的內容管理站點用不著下面所說的徹底分離什麼的,看看也無妨)

個人感覺前後台的情況有這麼幾種,首先是前後台是否是用一個驗證體系,其次是前後台是否共用一個數據表。

一般來說下面三種比較常用吧:

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

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

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

Yii2高級版裡面默認是A類型,即數據表一樣,且一邊登錄/登出了,另一邊也同樣登錄/登出,感覺這種結構比較適用於論壇這種,管理員也需要有與會員一樣發帖回帖等功能,表字段也基本一致,(個人這樣認為,畢竟接觸的不多,網上也搜過不同的後台構建的話題,但是很少有詳細討論的),這種可以通過字段、權限等來區分前後台。而我們將要做的是C類型,像是一些電商網站,後台的管理員和前台的會員功能就相差太大了,且表字段差別也大,所以驗證體系不一樣,而且放兩個數據表比較好。至於B類型算是C類型的簡化版,C如果會設置的話,B也同理。

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

1、yii2版本2.07以前用命令,即可在console/migrations目錄下創建一個php文件,然後在此文件下編寫創建表語句等等就可以了。

yii migrate/create admin

2、yii2版本2.07後,增加了更細致的分類,例如我已經創建了admin表,但少了一個status字段,那我可以直接用下面命令便會生成只增加字段的文件

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

生成:

<?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後面的參數總共匹配這幾種樣式:

1、create_junction_表名_and_表名,用來創建聯結表

2、add_xxx_to_表名,用來增加字段(可以用--fields樣式指定一個字段,否則生成空的,需要自己寫,當然也可以改模板添加個注釋示例)

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

4、create_表名,用來創建表

5、drop_表名,用來刪除表

注:可以直接在控制台用yii help migrate來查看更多的用法

模板文件可以在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);
}
}

具體語句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);
}
}

繼續運行下述命令行代碼,即可生成admin表,由於只是做演示,所以admin和user表基本一樣,不要在意這些細節。

yii migrate

好了,生成兩個表後,我們就需要將前台登錄和後台登陸徹底分開了:

1、前台修改:由於已經不公用了,所以先把公用的common/models中的User.php和LoginForm.php移動到frontend/models中去,順便將這兩個文件的命名空間改為以frontend開頭,將整個前台文件看一遍,把所有涉及到這兩個common文件命名空間的需要都改為前台自己的命名空間。

2、後台修改:同樣需要在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

然後再命令行中運行:

yii init/admin

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

3、現在我們前後台都能按照自己數據庫裡的數據來登錄了,但是由於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類型的驗證,而且集成了更多功能。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved