白狼栈 2016-09-07 08:44:09 19551次浏览 4条评论 13 1 0

作者:白狼 出处:http://www.manks.top/document/yii2-user.html 本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

上一章节我们讲述了如何通过新建数据模型来配置yii2的user组件,但是课后有小伙伴发来问卷,为啥在创建user_backend数据表的时候销毁了 password_reset_token 字段呢?其实这个字段对后台管理基本没啥子用,你要是非要,也可以,这里只对该字段以及用途做一个说明,课后需要的可以自行实现。

该字段具有唯一性,其用途在于用户找回密码。且该字段具有时效性,过期时间参考common\config\params.php文件的user.passwordResetTokenExpire项配置,过期时间默认是1小时。注意哦,默认的找回密码是基于邮件且发送的链接内容包含该字段,用于点击链接跳转后可根据该字段获取到具体用户并实现用户密码的修改。因为看起来还是蛮繁琐的,如果你没听懂,可以在【小站】​注册一个帐号,通过邮件找回密码测试一番。

因此,考虑到我们后台,无需这么繁琐,后面我们增加一个密码重置的功能,让用于自行修改密码即可。

说了那么多,我们接着上一章节,来说一说如何通过新建的数据表以及user组件来创建一个新的用户,以及如何实现新用户的登录机制。

其实也是so easy的,跟着步骤走,操作起来简单易学,一学就会,简直不能再6!
新用户的创建‘’
打开 index.php?r=user-backend 页面,我们发现有一个创建的按钮,当然,如果我们真的这么创建了,创建的用户肯定是废的,因为肯定不能登录嘛!至少密码我们这里没有加密吧,对不对?

接下来我们就来实现添加一个新用户的操作,然后一并实现其登陆的操作。

①、我们将【创建】的按钮改为【添加新用户】,并修改其对应的链接地址

<?= Html::a('添加新用户', ['signup'], ['class' => 'btn btn-success']) ?>

可以看到这里我们命名当前控制器的signup操作为添加新用户的操作,接着我们就去实现掉这个操作。

②、实现signup方法,注意哦,我们需要实现两步,分别是渲染添加用户的表单和处理表单提交的数据。

/**
 *  create new user
 */
public function actionSignup ()
{
    $model = new \backend\models\SignupForm();

    // 如果是post提交且有对提交的数据校验成功(我们在SignupForm的signup方法进行了实现)
    // $model->load() 方法,实质是把post过来的数据赋值给model
    // $model->signup() 方法, 是我们要实现的具体的添加用户操作
    if ($model->load(Yii::$app->request->post()) && $model->signup()) {
        return $this->redirect(['index']);
    }

    // 渲染添加新用户的表单
    return $this->render('signup', [
        'model' => $model,
    ]);
}

③、我们来看下渲染的表单文件signup.php,默认的视图文件存放在 views/user-backend/ 目录下,可以看到我们的表单页面是用bootstrap构建的,这样样式问题就不需要担心了。

<?php


/* @var $this yii\web\View */
/* @var $form yii\bootstrap\ActiveForm */
/* @var $model \backend\models\SignupForm */


use yii\helpers\Html;
use yii\bootstrap\ActiveForm;


$this->title = '添加新用户';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="site-signup">
    <div class="row">
        <div class="col-lg-5">
            <?php $form = ActiveForm::begin(['id' => 'form-signup']); ?>

                <?= $form->field($model, 'username')->textInput(['autofocus' => true]) ?>

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

                <?= $form->field($model, 'password')->passwordInput() ?>

                <div class="form-group">
                    <?= Html::submitButton('添加', ['class' => 'btn btn-primary', 'name' => 'signup-button']) ?>
                </div>

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

④、从第②、③步来看,我们紧接着要实现的是Signupform的signup方法,该方法的含义是把接收到的表单数据进行过滤验证然后入库操作。你不可能直接就把用户提交过来的数据直接入库了,比方说邮箱不合法呢?对表单的认证在yii2中操作起来是非常方便的,是需要配置model的rules规则即可。那有些人要问了,我的规则配置好了,什么时候校验呢?这个很简单,你只需要在数据入库之前调用一下model的validate方法或者save方法(save方法内部会调用validate方法)即可。

<?php
namespace backend\models;
use yii\base\Model;
use backend\models\UserBackend;


/**
 * Signup form
 */
class SignupForm extends Model
{
    public $username;
    public $email;
    public $password;


    /**
     * @inheritdoc
     * 对数据的校验规则
     */
    public function rules()
    {
        return [
            // 对username的值进行两边去空格过滤
            ['username', 'filter', 'filter' => 'trim'],
            
            // required表示必须的,也就是说表单提交过来的值必须要有, message 是username不满足required规则时给的提示消息
            ['username', 'required', 'message' => '用户名不可以为空'],
            
            // unique表示唯一性,targetClass表示的数据模型 这里就是说UserBackend模型对应的数据表字段username必须唯一
            ['username', 'unique', 'targetClass' => '\backend\models\UserBackend', 'message' => '用户名已存在.'],

            // string 字符串,这里我们限定的意思就是username至少包含2个字符,最多255个字符
            ['username', 'string', 'min' => 2, 'max' => 255],

            // 下面的规则基本上都同上,不解释了

            ['email', 'filter', 'filter' => 'trim'],
            ['email', 'required', 'message' => '邮箱不可以唯恐'],
            ['email', 'email'],
            ['email', 'string', 'max' => 255],
            ['email', 'unique', 'targetClass' => '\backend\models\UserBackend', 'message' => 'email已经被设置了.'],
            ['password', 'required', 'message' => '密码不可以为空'],
            ['password', 'string', 'min' => 6, 'tooShort' => '密码至少填写6位'],   
            // default 默认在没有数据的时候才会进行赋值
            [['created_at', 'updated_at'], 'default', 'value' => date('Y-m-d H:i:s')],
        ];
    }
    /**
     * Signs user up.
     *
     * @return true|false 添加成功或者添加失败
     */
    public function signup()
    {
        // 调用validate方法对表单数据进行验证,验证规则参考上面的rules方法
        if (!$this->validate()) {
            return null;
        }

        // 实现数据入库操作
        $user = new UserBackend();
        $user->username = $this->username;
        $user->email = $this->email;

        // 设置密码,密码肯定要加密,暂时我们还没有实现,看下面我们有实现的代码
        $user->setPassword($this->password);

        // 生成 "remember me" 认证key
        $user->generateAuthKey();

        // save(false)的意思是:不调用UserBackend的rules再做校验并实现数据入库操作
        // 这里这个false如果不加,save底层会调用UserBackend的rules方法再对数据进行一次校验,因为我们上面已经调用Signup的rules校验过了,这里就没必要在用UserBackend的rules校验了
        return $user->save(false);
    }
}

⑤、我们在SignupForm的signup操作中看到,需要实现UserBackend的setPassword和generateAuthKey方法,我们打开backend\models\UserBackend.php文件新增下面两个方法

/**
     * 为model的password_hash字段生成密码的hash值
     *
     * @param string $password
     */
    public function setPassword($password)
    {
        $this->password_hash = Yii::$app->security->generatePasswordHash($password);
    }

    /**
     * 生成 "remember me" 认证key
     */
    public function generateAuthKey()
    {
        $this->auth_key = Yii::$app->security->generateRandomString();
    }

现在我们添加新用户的界面是下面这样的(图见原文)
接着我们测试下添加一个新用户test1,发现也是可以的。(图见原文)
暂停一下,说了那么多,我们先回过头来缕缕实现的逻辑(分析图见原文)
登录的实现
[考虑目前国内网站大部分采集文章十分频繁,更有甚者不注明原文出处,原作者更希望看客们查看原文,以防有任何问题不能更新所有文章,避免误导!]

查看原文

觉得很赞
  • 评论于 2016-09-07 15:29 举报

    新手必备,好东西,赞一个 。

    , 觉得很赞
  • 评论于 2016-09-26 13:57 举报

    确实挺不错的!

    觉得很赞
  • 评论于 2017-02-26 21:32 举报

    照着写了下,注册和登录都实现了,非常不错!

  • 评论于 2017-11-18 21:44 举报

    楼主 我想问一下,如果我想在注册表单里面将副表新增加的一个字段在这里输入,比如昵称,在副表user_profile表新增加一个字段nickname,那我在注册的时候 这个用户的用户名和密码什么是写入到user表的,那怎么将用户填写的这个nickname更新到副表里面去呢,跟踪到方法里在model/user.php里面有一个afterInsertInternal方法,就是写入副表的:
    `$profile = new Profile();

        $this->link('profile', $profile);`
        我就是想问  我有一个nickname怎么传进去呢,我打印了下 发现这个nickname并没有获取到值
    
您需要登录后才可以评论。登录 | 立即注册