利用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制作静态网站的模板框架(三)
Oct 09 PHP
php实现利用phpexcel导出数据
Aug 24 PHP
对淘宝URL中ID提取的PHP代码
Sep 01 PHP
PHP的error_reporting错误级别变量对照表
Jul 08 PHP
ThinkPHP表单自动提交验证实例教程
Jul 18 PHP
Linux下安装PHP MSSQL扩展教程
Oct 24 PHP
详解WordPress中添加和执行动作的函数使用方法
Dec 29 PHP
学习PHP session的传递方式
Jun 15 PHP
详解PHP5.6.30与Apache2.4.x配置
Jun 02 PHP
php递归函数怎么用才有效
Feb 24 PHP
记录Yii2框架开发微信公众号遇到的问题及解决方法
Jul 20 PHP
PHP中遍历数组的三种常用方法实例分析
Jun 24 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
在php中使用sockets:从新闻组中获取文章
2006/10/09 PHP
使用sockets:从新闻组中获取文章(二)
2006/10/09 PHP
PHP Google的translate API代码
2008/12/10 PHP
php加水印的代码(支持半透明透明打水印,支持png透明背景)
2013/01/17 PHP
浅析php过滤html字符串,防止SQL注入的方法
2013/07/02 PHP
浅析get与post的一些特殊情况
2014/07/28 PHP
PHP的简单跳转提示的实现详解
2019/03/14 PHP
JQuery最佳实践之精妙的自定义事件
2010/08/11 Javascript
JS面向对象编程 for Cookie
2010/09/19 Javascript
javascript中的关于类型转换的性能优化
2010/12/14 Javascript
JavaScript lastIndexOf方法入门实例(计算指定字符在字符串中最后一次出现的位置)
2014/10/17 Javascript
javascript和jquery实现设置和移除文本框默认值效果代码
2015/01/13 Javascript
js实现鼠标感应图片展示的方法
2015/02/27 Javascript
浅谈被jQuery抛弃的函数及替代函数
2015/05/03 Javascript
基于Vue实现页面切换左右滑动效果
2020/06/29 Javascript
详解使用React进行组件库开发
2018/02/06 Javascript
浅探express路由和中间件的实现
2019/09/30 Javascript
JS实现打字游戏
2019/12/17 Javascript
[28:42]Ti4正赛VG vs NEWBEE1
2014/07/19 DOTA
[57:47]Fnatic vs Winstrike 2018国际邀请赛小组赛BO2 第二场 8.18
2018/08/19 DOTA
Python时区设置方法与pytz查询时区教程
2013/11/27 Python
python实现数据导出到excel的示例--普通格式
2018/05/03 Python
利用ctypes获取numpy数组的指针方法
2019/02/12 Python
python数据挖掘需要学的内容
2019/06/23 Python
纪伊国屋新加坡网上书店:Kinokuniya新加坡
2017/12/29 全球购物
美国最好的钓鱼、狩猎和划船装备商店:Bass Pro Shops
2018/12/02 全球购物
Servlet方面面试题
2016/09/28 面试题
优秀毕业生求职信范文
2014/01/02 职场文书
行政主管职责范本
2014/03/07 职场文书
人代会标语
2014/06/30 职场文书
创先争优活动心得体会
2014/09/04 职场文书
歌颂党的演讲稿
2014/09/10 职场文书
学习型党组织心得体会
2014/09/12 职场文书
圣诞节开幕词
2015/01/29 职场文书
Python Matplotlib绘制等高线图与渐变色扇形图
2022/04/14 Python
Vscode中SSH插件如何远程连接Linux
2022/05/02 Servers