示例详解Laravel重置密码代码重构


Posted in PHP onAugust 10, 2016

1、首先确定重置密码的路由

我们在安装好laravel的时候默认生成的重置密码是在用户未登录的情况下进行的。所以使用原来的控制器是不可行的,并且原有的重置密码,并不需要查看原始密码是否正确,而是通过邮件来进行直接更改密码,所以控制器方法的话,我们也需要重新写个。我们使用php artisan make:controller UserController创建一个控制器类,然后创建两条路由Route::get('reset', 'UserController@getReset')Route::post('reset', 'UserController@postReset')

前者是显示一个重置密码的页面get请求,后面是重置密码post请求。

2、显示重置密码页

这个使用的是getReset这个方法,这个方法只需要显示一个视图所以并没有特别的逻辑

public function getReset()
{
  return view('auth.reset');
}

3、请求重置密码

这个使用的是postReset这个方法,接收数据的话我们使用两种方法接收传过来的数据都可以:一种是使用request的方法接收数据另外一种是使用Input::get的方法获取数据Request的话需要引入use Illuminate\Http\Request类,Input的话需要引入use Input类,这里我们选择使用request来接收。

4、验证规则

验证的话,laravel为我们提供了一套验证的规则,使用validatorValidator::make()方法进行验证

$data = $request->all(); //接收所有的数据
$rules = [
  'oldpassword'=>'required|between:6,20',
  'password'=>'required|between:6,20|confirmed',
];
$messages = [
  'required' => '密码不能为空',
  'between' => '密码必须是6~20位之间',
  'confirmed' => '新密码和确认密码不匹配'
];
$validator = Validator::make($data, $rules, $messages);

$data 接收到从from传过来的数据信息;

rules 对接收到的值进行判断,其中数组前面的oldpasswordpassword是从前端from接收到的原始密码和新密码的name字段数据进行验证;

验证规则的话在手册的验证章节都有,值得注意的是,使用confirmed的话是为了新密码和确认密码进行相同判断,确认密码必须的name值必须是新密码的name值后面加上'_confirmation',比如新密码的name值为newpassword的话,确认密码的name值则必须为newpassword_confirmation才可以进行判断messages对验证的数据请求,显示什么提示。

然后通过上面的验证,还有个情况是没有验证的,那就是输入的原始密码是否和数据库里的原始密码相同。

这里我们可以先把这个用户的信息从数据库里给查出来,然后和输入的原始密码进行比对。这里我们使用Auth::user()来获取用户的信息,这个方法需要引入use Auth;类,然后通过Hash::check()来进行密码判断。判断完以后还有个问题,那就是,如何把错误信息给压入到validator的错误信息里,这里laravel为我们提供了after方法:

$user = Auth::user();
$validator->after(function($validator) use ($oldpassword, $user) {
  if (!\Hash::check($oldpassword, $user->password)) { //原始密码和数据库里的密码进行比对
    $validator->errors()->add('oldpassword', '原密码错误'); //错误的话显示原始密码错误
  }
});
if ($validator->fails()) {   //判断是否有错误
  return back()->withErrors($validator); //重定向页面,并把错误信息存入一次性session里
}
$user->password = bcrypt($password);    //使用bcrypt函数进行新密码加密
$user->save();   //成功后,保存新密码

这里因为after 引入了一个PHP的匿名函数,所以我们需要使用use 关键字把外部数据给传入到匿名函数里(PS:php新特性,闭包和匿名函数)

在匿名函数里我们引入了一个全局函数所以我们需要在函数前面加\(PS:php新特性,命名空间章节,全局命名空间)

5、前端显示错误信息

前端显示的话,我们使用$errors变量来显示错误,根据官方文档说明,调用的是Illuminate\Support\MessageBag的示例,有兴趣的话,可以看下。我们使用count($errors) > 0来判断是否有错误,使用 $errors->first()显示一条错误信息:

@if(count($errors) > 0)
  <div class="alert alert-danger display-hide" style="display: block;">
    <button class="close" data-close="alert"></button>
    <span>  </span>
  </div>
@endif

可能会有人问,如果我的错误不是显示在固定的一个地方,而是在每个表单的后面显示错误信息的话,这样我们该怎么判断和显示呢? 答案是使用$errors->has('oldpassword')来判断有没有这个名称的错误,如果有的话,使用 $errors->first('oldpassword') 显示这条错误:

@if( $errors->has('oldpassword') )
  <div class="alert alert-danger display-hide" style="display: block;">
    <button class="close" data-close="alert"></button>
    <span>  </span>
  </div>
@endif

其中oldpassword是每个表单的里的name值,所以在使用after方法添加自定义错误的时候 $validator->errors()->add('oldpassword', '原密码错误');中,oldpassword一定要写对是在哪个表单的错误,这样才能正确的显示。

6、完成后的示例

UserController

public function getReset()
{
  return view('auth.reset');
}

public function postReset(Request $request)
{
  $oldpassword = $request->input('oldpassword');
  $password = $request->input('password');
  $data = $request->all();
  $rules = [
    'oldpassword'=>'required|between:6,20',
    'password'=>'required|between:6,20|confirmed',
  ];
  $messages = [
    'required' => '密码不能为空',
    'between' => '密码必须是6~20位之间',
    'confirmed' => '新密码和确认密码不匹配'
  ];
  $validator = Validator::make($data, $rules, $messages);
  $user = Auth::user();
  $validator->after(function($validator) use ($oldpassword, $user) {
    if (!\Hash::check($oldpassword, $user->password)) {
      $validator->errors()->add('oldpassword', '原密码错误');
    }
  });
  if ($validator->fails()) {
    return back()->withErrors($validator); //返回一次性错误
  }
  $user->password = bcrypt($password);
  $user->save();
  Auth::logout(); //更改完这次密码后,退出这个用户
  return redirect('/login');
}

reset.blade

<form class="login-form" action="" method="post">
    <h3 class="font-green">修改密码</h3>
    @if($errors->first())
      <div class="alert alert-danger display-hide" style="display: block;">
        <button class="close" data-close="alert"></button>
        <span>  </span>
      </div>
    @endif
    {!! csrf_field() !!}

    <div class="form-group">
      <label class="control-label visible-ie8 visible-ie9">原始密码</label>
      <input class="form-control placeholder-no-fix" type="password" autocomplete="off" placeholder="Old Password" name="oldpassword"> </div>
    <div class="form-group">
      <label class="control-label visible-ie8 visible-ie9">新密码</label>
      <input class="form-control placeholder-no-fix" type="password" autocomplete="off" id="register_password" placeholder="New password" name="password"> </div>
    <div class="form-group">
      <label class="control-label visible-ie8 visible-ie9">重复密码</label>
      <input class="form-control placeholder-no-fix" type="password" autocomplete="off" placeholder="Repeat password" name="password_confirmation"> </div>
    <div class="form-actions">
      <button type="submit" id="register-submit-btn" class="btn btn-success uppercase pull-right">确定</button>
    </div>
  </form>

总结

以上就是本文的全部内容,希望对大家学习使用Laravel有所帮助,如果有疑问的话欢迎留言讨论。

原文:Dennis`s blog

PHP 相关文章推荐
如何跨站抓取别的站点的页面的补充
Oct 09 PHP
用PHP 快速生成 Flash 动画的方法
Mar 06 PHP
PHP连接access数据库
Mar 27 PHP
apache mysql php 源码编译使用方法
May 03 PHP
PHP aes (ecb)解密后乱码问题
Jun 22 PHP
浅谈php提交form表单
Jul 01 PHP
详解PHP中的PDO类
Jul 06 PHP
Zend Framework教程之前端控制器Zend_Controller_Front用法详解
Mar 07 PHP
thinkPHP+PHPExcel实现读取文件日期的方法(含时分秒)
Jul 07 PHP
php+jquery+html实现点击不刷新加载更多的实例代码
Aug 12 PHP
PHP实现打包下载文件的方法示例
Oct 07 PHP
laravel validate 设置为中文的例子(验证提示为中文)
Sep 29 PHP
修改Laravel5.3中的路由文件与路径
Aug 10 #PHP
Yii2中关联查询简单用法示例
Aug 10 #PHP
Yii2实现让关联字段支持搜索功能的方法
Aug 10 #PHP
Yii2实现同时搜索多个字段的方法
Aug 10 #PHP
Yii2实现上下联动下拉框功能的方法
Aug 10 #PHP
Yii2基于Ajax自动获取表单数据的方法
Aug 10 #PHP
教你在header中隐藏php的版本信息
Aug 10 #PHP
You might like
改写函数实现PHP二维/三维数组转字符串
2013/09/13 PHP
PHP中file_get_contents函数抓取https地址出错的解决方法(两种方法)
2015/09/22 PHP
php实现数据库的增删改查
2017/02/26 PHP
关于PHP定时发送服务的解决办法
2017/04/23 PHP
PHP配置ZendOpcache插件加速
2019/02/14 PHP
PHP实现的抓取小说网站内容功能示例
2019/06/27 PHP
php7性能提升的原因详解
2019/10/13 PHP
PHP读取Excel内的图片(phpspreadsheet和PHPExcel扩展库)
2019/11/19 PHP
简单的无缝滚动程序-仅几行代码
2007/05/08 Javascript
html超链接打开窗口大小的方法
2013/03/05 Javascript
javascript中with()方法的语法格式及使用
2014/08/04 Javascript
黑帽seo劫持程序,js劫持搜索引擎代码
2015/09/15 Javascript
KnockoutJS 3.X API 第四章之数据控制流if绑定和ifnot绑定
2016/10/10 Javascript
jQuery插件FusionCharts实现的2D柱状图效果示例【附demo源码下载】
2017/03/06 Javascript
微信小程序开发之从相册获取图片 使用相机拍照 本地图片上传
2017/04/18 Javascript
史上最全JavaScript数组去重的十种方法(推荐)
2017/08/17 Javascript
jquery实现左右轮播切换效果
2018/01/01 jQuery
NodeJS实现自定义流的方法
2018/08/01 NodeJs
基于JavaScript实现留言板功能
2020/03/16 Javascript
详解elementUI中input框无法输入的问题
2020/04/27 Javascript
如何在JavaScript中正确处理变量
2020/12/25 Javascript
[01:27:44]DOTA2-DPC中国联赛 正赛 PSG.LGD vs Aster BO3 第一场 1月24日
2021/03/11 DOTA
将string类型的数据类型转换为spark rdd时报错的解决方法
2019/02/18 Python
Python 实现遥感影像波段组合的示例代码
2019/08/04 Python
在python3中使用shuffle函数要注意的地方
2020/02/28 Python
keras多显卡训练方式
2020/06/10 Python
aec加密 php_php aes加密解密类(兼容php5、php7)
2021/03/14 PHP
HTML5 虚拟键盘出现挡住输入框的解决办法
2017/02/14 HTML / CSS
什么是smarty? Smarty的优点是什么?
2013/08/11 面试题
办公室内勤岗位职责范本
2013/12/09 职场文书
美术课外活动总结
2014/07/08 职场文书
财政专业大学生职业生涯规划书
2014/09/17 职场文书
世界遗产的导游词
2015/02/13 职场文书
单位证明范文
2015/06/18 职场文书
导游词之香港-太平山顶
2019/10/18 职场文书
python中的mysql数据库LIKE操作符详解
2021/07/01 MySQL