利用Laravel事件系统如何实现登录日志的记录详解


Posted in PHP onMay 20, 2017

本文介绍的是利用Laravel事件系统实现登录日志记录的相关内容,分享出来给大家参考,下面来看看详细的介绍:

明确需求

记录一个登录日志,通常需要下列信息:

  • 客户端Agent信息
  • 客户端IP地址
  • 访问IP地点
  • 登录时间
  • 登录用户信息

确立工具

明确完需求后,根据每个需求查找自己所需的工具吧。

  • 需求1 jenssegers/agent就可以满足我们要求
  • 需求2 Laravel下直接Request::getClientIp()
  • 需求3 zhuzhichao/ip-location-zh这个包可以满足要求
  • 需求4 time()
  • 需求5 登录用户模型

开工

采用Laravel的事件订阅系统来实现,需要实现一个登录事件和一个登录事件监听器。

生成事件和监听器

Laravel命令行支持自动生成事件和监听器,在App\Providers\EventServiceProvider中添加需要实现的事件:

protected $listen = [ 
  ...,
  //添加登录事件及对应监听器,一个事件可绑定多个监听器
  'App\Events\LoginEvent' => [
  'App\Listeners\LoginListener',
 ],
];

运行命令:php artisan event:generate就会自动生成事件和监听器,已存在的事件和监听器不会发生改变。

登录事件(Event)

回顾下需求,我们的登录事件需要的5点信息,在事件中需要记录这些信息,所以事件设计如下:

namespace App\Events;

use Illuminate\Broadcasting\Channel; 
use Illuminate\Queue\SerializesModels; 
use Illuminate\Broadcasting\PrivateChannel; 
use Illuminate\Foundation\Events\Dispatchable; 
use Illuminate\Broadcasting\InteractsWithSockets;

use App\Models\User; 
use Jenssegers\Agent\Agent;

class LoginEvent 
{
 use Dispatchable, InteractsWithSockets, SerializesModels;

 /**
 * @var User 用户模型
 */
 protected $user;

 /**
 * @var Agent Agent对象
 */
 protected $agent;

 /**
 * @var string IP地址
 */
 protected $ip;

 /**
 * @var int 登录时间戳
 */
 protected $timestamp;

 /**
 * 实例化事件时传递这些信息
 */
 public function __construct($user, $agent, $ip, $timestamp)
 {
 $this->user = $user;
 $this->agent = $agent;
 $this->ip = $ip;
 $this->timestamp = $timestamp;
 }

 public function getUser()
 {
 return $this->user;
 }

 public function getAgent()
 {
 return $this->agent;
 }

 public function getIp()
 {
 return $this->ip;
 }

 public function getTimestamp()
 {
 return $this->timestamp;
 }

 /**
 * Get the channels the event should broadcast on.
 *
 * @return Channel|array
 */
 public function broadcastOn()
 {
 return new PrivateChannel('channel-default');
 }
}

在事件中记录所需要的信息,并实现这些信息的get方法。

登录监听器(Listener)

在监听器中,获取到事件传递过来的信息,把这些信息记录到数据库中,实现如下:

namespace App\Listeners;

use App\Events\LoginEvent;

class LoginListener 
{

 // handle方法中处理事件
 public function handle(LoginEvent $event)
 {
 //获取事件中保存的信息
 $user = $event->getUser();
 $agent = $event->getAgent();
 $ip = $event->getIp();
 $timestamp = $event->getTimestamp();

 //登录信息
 $login_info = [
  'ip' => $ip,
  'login_time' => $timestamp,
  'user_id' => $user->id
 ];

 // zhuzhichao/ip-location-zh 包含的方法获取ip地理位置
 $addresses = \Ip::find($ip);
 $login_info['address'] = implode(' ', $addresses);

 // jenssegers/agent 的方法来提取agent信息
 $login_info['device'] = $agent->device(); //设备名称
 $browser = $agent->browser();  
 $login_info['browser'] = $browser . ' ' . $agent->version($browser); //浏览器
 $platform = $agent->platform();
 $login_info['platform'] = $platform . ' ' . $agent->version($platform); //操作系统
 $login_info['language'] = implode(',', $agent->languages()); //语言
 //设备类型
 if ($agent->isTablet()) {
  // 平板
  $login_info['device_type'] = 'tablet';
 } else if ($agent->isMobile()) {
  // 便捷设备
  $login_info['device_type'] = 'mobile';
 } else if ($agent->isRobot()) {
  // 爬虫机器人
  $login_info['device_type'] = 'robot';
  $login_info['device'] = $agent->robot(); //机器人名称
 } else {
  // 桌面设备
  $login_info['device_type'] = 'desktop';
 }

 //插入到数据库
 DB::table('login_log')->insert($login_info);

 } 
}

这样,监听器就完成了,每次一触发登录事件,就会在数据库中添加一条登录信息。

触发事件

通过全局的event()方法来触发事件,event()方法的参数为事件实例:

namespace App\Controllers; 
...
use App\Events\LoginEvent; 
use Jenssegers\Agent\Agent; 
class AuthControoler extends Controller 
{
 ...
 public function login(Request $request)
 {
 //登录实现
 ...
 //登录成功,触发事件
 event(new LoginEvent($this->guard()->user(), new Agent(), \Request::getClientIp(), time()));
 ... 
 } 
}

队列化监听器

有时监听器会进行一些耗时操作,这时应该结合Laravel的队列系统将监听器进行队列化,前提是已经配置了队列并开启了队列处理器。

队列化非常简单,只需监听器实现ShouldQueue接口即可,即:

namespace App\Listeners; 
...
use Illuminate\Contracts\Queue\ShouldQueue; 
class LoginListener implements ShouldQueue 
{
 /**
 * 失败重试次数
 * @var int
 */
 public $tries = 1;
 ...
}

总结

Laravel的事件系统实现起来还是非常优雅的,同一个事件可以很方便的添加各类监听器,且各个监听器之间互不干扰,解耦性非常强。加上队列系统,可以很方便的处理一些后续任务。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

PHP 相关文章推荐
php.ini中文版
Oct 09 PHP
PHP通过header实现文本文件下载的代码
Aug 08 PHP
解析CI即CodeIgniter框架在Nginx下的重写规则
Jun 03 PHP
PHP使用Session遇到的一个Permission denied Notice解决办法
Jul 30 PHP
Discuz7.2版的faq.php SQL注入漏洞分析
Aug 06 PHP
关于WordPress的SEO优化相关的一些PHP页面脚本技巧
Dec 10 PHP
基于laravel制作APP接口(API)
Mar 15 PHP
PHP进行批量任务处理不超时的解决方法
Jul 11 PHP
PHP自定义函数获取URL中一级域名的方法
Aug 23 PHP
老生常谈PHP数组函数array_merge(必看篇)
May 25 PHP
php curl批处理实现可控并发异步操作示例
May 09 PHP
PDO::errorCode讲解
Jan 28 PHP
Yii框架实现图片上传的方法详解
May 20 #PHP
Yii框架分页实现方法详解
May 20 #PHP
thinkPHP显示不出验证码的原因与解决方法分析
May 20 #PHP
yii2项目实战之restful api授权验证详解
May 20 #PHP
ThinkPHP下表单令牌错误与解决方法分析
May 20 #PHP
PHP那些琐碎的知识点(整理)
May 20 #PHP
PHP使用xpath解析XML的方法详解
May 20 #PHP
You might like
Get或Post提交值的非法数据处理
2006/10/09 PHP
计算2000年01月01日起到指定日的天数
2006/10/09 PHP
php生成静态页面的简单示例
2014/04/17 PHP
微信公众平台开发教程④ ThinkPHP框架下微信支付功能图文详解
2019/04/10 PHP
laravel-admin表单提交隐藏一些数据,回调时获取数据的方法
2019/10/08 PHP
JavaScript触发器详解
2007/03/10 Javascript
js生成动态表格并为每个单元格添加单击事件的方法
2014/04/14 Javascript
js的image onload事件使用遇到的问题
2014/07/15 Javascript
apply和call方法定义及apply和call方法的区别
2015/11/15 Javascript
Bootstrap页面布局基础知识全面解析
2016/06/13 Javascript
js eval函数使用,js对象和字符串互转实例
2017/03/06 Javascript
微信小程序 监听手势滑动切换页面实例详解
2017/06/15 Javascript
解析Vue 2.5的Diff算法
2017/11/28 Javascript
JavaScript实现的简单Tab点击切换功能示例
2018/07/06 Javascript
vue拖拽组件 vuedraggable API options实现盒子之间相互拖拽排序
2019/07/08 Javascript
js Array.slice的8种不同用法示例
2019/07/10 Javascript
在vue中封装方法以及多处引用该方法详解
2020/08/14 Javascript
Python中函数eval和ast.literal_eval的区别详解
2017/08/10 Python
对python中Librosa的mfcc步骤详解
2019/01/09 Python
python中的decimal类型转换实例详解
2019/06/26 Python
python Web flask 视图内容和模板实现代码
2019/08/23 Python
python3获取url文件大小示例代码
2019/09/18 Python
pytorch制作自己的LMDB数据操作示例
2019/12/18 Python
python GUI库图形界面开发之pyinstaller打包python程序为exe安装文件
2020/02/26 Python
jupyter notebook 多行输出实例
2020/04/09 Python
python 实现 hive中类似 lateral view explode的功能示例
2020/05/18 Python
HTML5安全介绍之内容安全策略(CSP)简介
2012/07/10 HTML / CSS
高性能装备提升营地:Kammok
2019/02/27 全球购物
ellesse美国官方商店:意大利高级运动服品牌
2019/10/29 全球购物
有趣、实用和鼓舞人心的产品:Inspire Uplift
2019/11/05 全球购物
Order by的几种用法
2013/06/16 面试题
介绍一下Java中的static关键字
2012/05/12 面试题
巾帼文明岗事迹材料
2014/12/24 职场文书
综合素质评价个性发展自我评价
2015/03/06 职场文书
2016年领导干部正风肃纪心得体会
2015/10/09 职场文书
导游词之唐山景点
2019/12/18 职场文书