> php教程 > php手册 > 본문

Yii2的相关学习记录,前后台分离及migrate使用(七) - 漫游云巅

WBOY
풀어 주다: 2016-05-20 10:14:54
원래의
1144명이 탐색했습니다.

最近一直忙其它的(其实是懒!),将《深入理解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:<span style="color: #0000ff;">int</span>(<span style="color: #800080;">10</span>):nontNull
로그인 후 복사

生成:

<span style="color: #000000;">php
</span><span style="color: #0000ff;">use</span><span style="color: #000000;"> yii\db\Migration;

</span><span style="color: #0000ff;">class</span> m160501_053640_add_column_to_admin <span style="color: #0000ff;">extends</span><span style="color: #000000;"> Migration
{
    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> up()
    {
        </span><span style="color: #800080;">$this</span>->addColumn('admin', 'status', <span style="color: #800080;">$this</span>->int(10)-><span style="color: #000000;">nontNull());
    }

    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> down()
    {
        </span><span style="color: #800080;">$this</span>->dropColumn('admin', 'status'<span style="color: #000000;">);
    }
}</span>
로그인 후 복사

具体为什么会这样,我们看下原代码,在vendor/yiisoft/yii2/console/BaseMigrateController.php文件的actionCreate方法中:

...<span style="color: #000000;">
} </span><span style="color: #0000ff;">elseif</span> (<span style="color: #008080;">preg_match</span>('/^add_(.+)_to_(.+)$/', <span style="color: #800080;">$name</span>, <span style="color: #800080;">$matches</span><span style="color: #000000;">)) {
    </span><span style="color: #800080;">$content</span> = <span style="color: #800080;">$this</span>->renderFile(Yii::getAlias(<span style="color: #800080;">$this</span>->generatorTemplateFiles['add_column']),<span style="color: #000000;"> [
        </span>'className' => <span style="color: #800080;">$className</span>,
        'table' => mb_strtolower(<span style="color: #800080;">$matches</span>[2], Yii::<span style="color: #800080;">$app</span>->charset),
        'fields' => <span style="color: #800080;">$this</span>-><span style="color: #000000;">fields
    ]);
}
</span>...
로그인 후 복사

我们可以看到,这里是正则匹配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中修改

<span style="color: #0000ff;">return</span><span style="color: #000000;"> [
    </span><span style="color: #008000;">//</span><span style="color: #008000;">修改migration模板</span>
    'controllerMap' =><span style="color: #000000;"> [
        </span>'migrate' =><span style="color: #000000;"> [
            </span>'class' => 'yii\console\controllers\MigrateController',
            'templateFile'=>'@yii/views/migration.php',<span style="color: #008000;">//</span><span style="color: #008000;">默认模板,2.07后应该很少用了</span>
            'generatorTemplateFiles' =><span style="color: #000000;"> [
                </span>'create_table' => '@console/views/createTableMigration.php',<span style="color: #008000;">//</span><span style="color: #008000;">修改的</span>
                'drop_table' => '@yii/views/dropTableMigration.php',<span style="color: #008000;">//</span><span style="color: #008000;">未修改的</span>
                'add_column' => '@console/views/addColumnMigration.php',<span style="color: #008000;">//</span><span style="color: #008000;">修改的</span>
                'drop_column' => '@console/views/dropColumnMigration.php',<span style="color: #008000;">//</span><span style="color: #008000;">修改的</span>
                'create_junction' => '@yii/views/createJunctionMigration.php'<span style="color: #008000;">//</span><span style="color: #008000;">未修改的</span>
            ],<span style="color: #000000;">
        ]</span>,<span style="color: #000000;">
    ]</span>,<span style="color: #000000;">
];</span>
로그인 후 복사

值得注意的是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:

<span style="color: #000000;">php
</span><span style="color: #008000;">/*</span><span style="color: #008000;">*
 * This view is used by console/controllers/MigrateController.php
 * The following variables are available in this view:
 </span><span style="color: #008000;">*/</span>
<span style="color: #008000;">/*</span><span style="color: #008000;"> @var $className string the new migration class name </span><span style="color: #008000;">*/</span>
<span style="color: #008000;">/*</span><span style="color: #008000;"> @var $table string the name table </span><span style="color: #008000;">*/</span>
<span style="color: #008000;">/*</span><span style="color: #008000;"> @var $fields array the fields </span><span style="color: #008000;">*/</span>

<span style="color: #0000ff;">echo</span> "<?php \n"<span style="color: #000000;">;
?>

<span style="color: #0000ff;">use</span><span style="color: #000000;"> yii\db\Migration;

</span><span style="color: #0000ff;">class</span> = <span style="color: #800080;">$className</span> ?> <span style="color: #0000ff;">extends</span><span style="color: #000000;"> Migration
{
    </span><span style="color: #0000ff;">const</span> TBL_NAME = '{{%=$table?>}}'<span style="color: #000000;">;
    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> up()
    {
        </span><span style="color: #800080;">$tableOptions</span> = <span style="color: #0000ff;">null</span><span style="color: #000000;">;
        </span><span style="color: #0000ff;">if</span> (<span style="color: #800080;">$this</span>->db->driverName === 'mysql'<span style="color: #000000;">) {
            </span><span style="color: #800080;">$tableOptions</span> = 'CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE=InnoDB COMMENT="填写表注释"'<span style="color: #000000;">;
        }
        </span><span style="color: #800080;">$this</span>->createTable(self::TBL_NAME,<span style="color: #000000;"> [
</span><?php <span style="color: #0000ff;">foreach (<span style="color: #800080;">$fields</span> <span style="color: #0000ff;">as</span> <span style="color: #800080;">$field</span>): ?>
<?php <span style="color: #0000ff;">if (<span style="color: #800080;">$field</span> == <span style="color: #008080;">end</span>(<span style="color: #800080;">$fields</span>)): ?>
            '= $field['property'] ?>' => <span style="color: #800080;">$this</span>->= <span style="color: #800080;">$field</span>['decorators'].".\" COMMENT '填写段注释'\"" . "\n"?>
<?php <span style="color: #0000ff;">else: ?>
            '= $field['property'] ?>' => <span style="color: #800080;">$this</span>->= <span style="color: #800080;">$field</span>['decorators'].".\" COMMENT '填写段注释'\"" . ",\n"?>
<?php <span style="color: #0000ff;">endif; ?>
<?php <span style="color: #0000ff;">endforeach; ?><span style="color: #000000;">
        ]</span>,<span style="color: #800080;">$tableOptions</span><span style="color: #000000;">);
    }

    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> down()
    {
        </span><span style="color: #800080;">$this</span>->dropTable(self::<span style="color: #000000;">TBL_NAME);
    }
}</span>
로그인 후 복사
createTableMigration.php

 具体语句m160326_133655_create_admin.php:

<span style="color: #000000;">php

</span><span style="color: #0000ff;">use</span><span style="color: #000000;"> yii\db\Migration;

</span><span style="color: #0000ff;">class</span> m160427_133556_create_admin <span style="color: #0000ff;">extends</span><span style="color: #000000;"> Migration
{
    </span><span style="color: #0000ff;">const</span> TBL_NAME = '{{%admin}}'<span style="color: #000000;">;
    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> up()
    {
        </span><span style="color: #800080;">$tableOptions</span> = <span style="color: #0000ff;">null</span><span style="color: #000000;">;
        </span><span style="color: #0000ff;">if</span> (<span style="color: #800080;">$this</span>->db->driverName === 'mysql'<span style="color: #000000;">) {
            </span><span style="color: #800080;">$tableOptions</span> = 'CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE=InnoDB COMMENT="后台管理员表"'<span style="color: #000000;">;
        }
        </span><span style="color: #800080;">$this</span>->createTable(self::TBL_NAME,<span style="color: #000000;"> [
             </span>'id' => <span style="color: #800080;">$this</span>->primaryKey(),
            'username'=><span style="color: #800080;">$this</span>-><span style="color: #0000ff;">string</span>()->notNull()->unique()." COMMENT '用户名'",
            'auth_key'=><span style="color: #800080;">$this</span>-><span style="color: #0000ff;">string</span>(32)->notNull()." COMMENT '认证Key'",
            'password_hash'=><span style="color: #800080;">$this</span>-><span style="color: #0000ff;">string</span>()->notNull()." COMMENT '密码'",
            'password_reset_token'=><span style="color: #800080;">$this</span>-><span style="color: #0000ff;">string</span>()->unique()." COMMENT '密码重置Token'",
            'email'=><span style="color: #800080;">$this</span>-><span style="color: #0000ff;">string</span>()->notNull()->unique()." COMMENT '邮箱'",
            'status'=><span style="color: #800080;">$this</span>->smallInteger()->notNull()->defaultValue(10)." COMMENT '状态'",
            'created_at' => <span style="color: #800080;">$this</span>-><span style="color: #0000ff;">integer</span>()->notNull()." COMMENT '创建时间'",
            'updated_at' => <span style="color: #800080;">$this</span>-><span style="color: #0000ff;">integer</span>()->notNull()." COMMENT '更新时间'",<span style="color: #000000;">
        ]</span>,<span style="color: #800080;">$tableOptions</span><span style="color: #000000;">);
    }

    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> down()
    {
        </span><span style="color: #800080;">$this</span>->dropTable(self::<span style="color: #000000;">TBL_NAME);
    }
}</span>
로그인 후 복사
xxx_create_admin.php

继续运行下述命令行代码,即可生成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,然后如下代码:

<span style="color: #000000;">php
</span><span style="color: #008000;">/*</span><span style="color: #008000;">*
 * Application initialization
 * 参照深入理解Yii2.0视频教程
 </span><span style="color: #008000;">*/</span><span style="color: #000000;">
namespace console\controllers;

</span><span style="color: #0000ff;">use</span><span style="color: #000000;"> backend\models\Admin;

</span><span style="color: #0000ff;">class</span> InitController <span style="color: #0000ff;">extends</span><span style="color: #000000;"> \yii\console\Controller
{
    </span><span style="color: #008000;">/*</span><span style="color: #008000;">*
     * Create init admin
     </span><span style="color: #008000;">*/</span>
    <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> actionAdmin()
    {
        </span><span style="color: #0000ff;">echo</span> "Create init admin ...\n";                  <span style="color: #008000;">//</span><span style="color: #008000;"> 提示当前操作</span>
        <span style="color: #800080;">$username</span> = <span style="color: #800080;">$this</span>->prompt('Admin Name:');        <span style="color: #008000;">//</span><span style="color: #008000;"> 接收用户名</span>
        <span style="color: #800080;">$email</span> = <span style="color: #800080;">$this</span>->prompt('Email:');               <span style="color: #008000;">//</span><span style="color: #008000;"> 接收Email</span>
        <span style="color: #800080;">$password</span> = <span style="color: #800080;">$this</span>->prompt('Password:');         <span style="color: #008000;">//</span><span style="color: #008000;"> 接收密码</span>
        <span style="color: #800080;">$model</span> = <span style="color: #0000ff;">new</span> Admin();                            <span style="color: #008000;">//</span><span style="color: #008000;"> 创建一个新用户</span>
        <span style="color: #800080;">$model</span>->username = <span style="color: #800080;">$username</span>;                   <span style="color: #008000;">//</span><span style="color: #008000;"> 完成赋值</span>
        <span style="color: #800080;">$model</span>->email = <span style="color: #800080;">$email</span><span style="color: #000000;">;
        </span><span style="color: #800080;">$model</span>->password = <span style="color: #800080;">$password</span>;<span style="color: #008000;">//</span><span style="color: #008000;">注意这个地方,用了Admin模型中的setPassword方法(魔术方法__set)</span>
        <span style="color: #0000ff;">if</span> (!<span style="color: #800080;">$model</span>->save())                            <span style="color: #008000;">//</span><span style="color: #008000;"> 保存新的用户</span>
<span style="color: #000000;">        {
            </span><span style="color: #0000ff;">foreach</span> (<span style="color: #800080;">$model</span>->getErrors() <span style="color: #0000ff;">as</span> <span style="color: #800080;">$error</span>)     <span style="color: #008000;">//</span><span style="color: #008000;"> 如果保存失败,说明有错误,那就输出错误信息。</span>
<span style="color: #000000;">            {
                </span><span style="color: #0000ff;">foreach</span> (<span style="color: #800080;">$error</span> <span style="color: #0000ff;">as</span> <span style="color: #800080;">$e</span><span style="color: #000000;">)
                {
                    </span><span style="color: #0000ff;">echo</span> "<span style="color: #800080;">$e</span>\n"<span style="color: #000000;">;
                }
            }
            </span><span style="color: #0000ff;">return</span> 1;                                   <span style="color: #008000;">//</span><span style="color: #008000;"> 命令行返回1表示有异常</span>
<span style="color: #000000;">        }
        </span><span style="color: #0000ff;">return</span> 0;                                       <span style="color: #008000;">//</span><span style="color: #008000;"> 返回0表示一切OK</span>
<span style="color: #000000;">    }

}

InitController</span>.php
로그인 후 복사
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' =><span style="color: #000000;"> [
    </span>'user' =><span style="color: #000000;"> [
        </span>'identityClass' => 'backend\models\Admin',
        'enableAutoLogin' => <span style="color: #0000ff;">true</span>,
        'identityCookie' =><span style="color: #000000;"> [
            </span>'name' => '_backendUser', <span style="color: #008000;">//</span><span style="color: #008000;"> unique for backend</span>
        ],<span style="color: #000000;">
    ]</span>,
    'session' =><span style="color: #000000;"> [
        </span>'name' => 'PHPBACKSESSID',
        'savePath' => sys_get_temp_dir(),<span style="color: #000000;">
    ]</span>,
    'request' =><span style="color: #000000;"> [
        </span>'cookieValidationKey' => 'orGkZNZvZe3-4WicYHyGMS-EyI6Tp8yi',<span style="color: #008000;">//</span><span style="color: #008000;">random string</span>
        'csrfParam' => '_backendCSRF',<span style="color: #000000;">
    ]</span>,
...
로그인 후 복사

同样在前台,在frontend/config/main.php或者main-local.php中

'components' =><span style="color: #000000;"> [
    </span>'user' =><span style="color: #000000;"> [
        </span>'identityClass' => 'frontend\models\User',
        'enableAutoLogin' => <span style="color: #0000ff;">true</span>,
        'identityCookie' =><span style="color: #000000;"> [
            </span>'name' => '_frontendUser', <span style="color: #008000;">//</span><span style="color: #008000;"> unique for frontend</span>
<span style="color: #000000;">        ]
    ]</span>,
    'session' =><span style="color: #000000;"> [
        </span>'name' => 'PHPFRONTSESSID',
        'savePath' => sys_get_temp_dir(),<span style="color: #000000;">
    ]</span>,
    'request' =><span style="color: #000000;"> [
        </span>'cookieValidationKey' => '8rqO22WJ9yiAx_KuJ8SFnbKctqGDWi9J',
        'csrfParam' => '_frontendCSRF',<span style="color: #000000;">
    ]</span>,
...
로그인 후 복사

这样再登陆试下,就会发现前后台完全没关联了。可以调用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类型的验证,而且集成了更多功能。(个人只是大体看了下,没下载使用呢还)

원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 추천
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿