侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

在Laravel项目中使用中间件方式统计用户在线时长功能代码示例

Laravel  /  管理员 发布于 2个月前   67

需求:Laravel 项目,需 了解用户上次在线的时间以及总计在线时长

需要使用的表:

此处以统计后台用户(admin_users)的在线时长为例;

前台用户的话,只是对应的表不一样 (对应 users);

准备数据库:

此处需要添加两个字段,分别是 上次在线时间 和 总计在线时长(秒为单位):

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class AddSpentToAdminUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('admin_users', function (Blueprint $table) {
            $table->unsignedInteger('spent')->default('0')->comment('使用时长')->after('id');
            $table->timestamp('onlined_at')->nullable()->comment('最后访问时间')->after('updated_at');
        });
    }
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('admin_users', function (Blueprint $table) {
            //
            $table->dropColumn(['spent', 'onlined_at']);
        });
    }
}


创建中间件:

<?php
namespace App\Http\Middleware;
use Carbon\Carbon;
use Closure;
use Dcat\Admin\Admin;
use Illuminate\Support\Facades\Cache;

class CountAdminUserOnlineTime
{
    public function handle($request, Closure $next)
    {
        $user = Admin::user(); // 获取当前认证用户
        //dd($user);
        if ($user) {
            $seenKey = 'auser-last-seen-'; //缓存标识
            $lastSeenAt = Cache::get($seenKey . $user->id); // 获取上次访问时间戳
            $now = Carbon::now();
            if ($lastSeenAt != null) {
                $duration = $now->diffInSeconds($lastSeenAt); // 计算在线时长(秒数)
                $user->increment('spent', $duration, ['updated_at' => $user->updated_at, 'onlined_at' => $now]); //updated_at 维持原值
            }
            Cache::put($seenKey . $user->id, $now, Carbon::now()->addMinutes(1)); // 保存当前访问时间戳(并设置缓存过期时间为一分钟)
        }
        return $next($request);
    }
}

此处没有用使用 DB facade 来避免更新用户表的 {更新时间} 字段,

而用 increment 函数的第二个参数来维持 updated_at 值不变。


配置中间件

在\app\Http\Kernel.php中添加一个$routeMiddleware

protected $routeMiddleware = [
        //其它
        'admin.spent' => \App\Http\Middleware\CountAdminUserOnlineTime::class,
        //其它
    ];

如果你用的是dcat-admin后台框架

可以在config/admin.php的route配置里直接附加middleware:

'middleware' => ['web', 'admin'], // 默认值:
'middleware' => ['web', 'admin', 'admin.spent'], //添加在线时长中间件

其它情况

在路由定义里添加:

Route::middleware([/* 其它中间件*/ , 'admin.spent'])->group(
function () {
    //... 需要统计的路由
});


下面这里以dcat admin为例

dcat-admin在概览页面展示用户时长:

//新建一个 AdminUser 模型继承默认的 Administrator
<?php

namespace App\Models;
use Dcat\Admin\Models\Administrator;

class AdminUser extends Administrator
{
}

//在线时间表格
use Carbon\Carbon;
use Dcat\Admin\Widgets\Callout;
use Dcat\Admin\Widgets\Tab;
use Dcat\Admin\Widgets\Table;
...
public static function tab()
    {
        $data = AdminUser::query()
            ->orderBy('onlined_at', 'DESC')
            ->get(['name', 'onlined_at', 'spent'])
            ->toArray();
        foreach ($data as &$d) {
            if (!$d['spent']) {
                $d['spent'] = '-';
            } else {
                $d['spent'] = formatTime($d['spent']);
            }
            if (Carbon::parse($d['onlined_at'])->diffInMinutes() <= 5) {
                $d['name'] = '<i class="fa fa-circle" style="font-size: 13px;color: #4e9876"></i>&ensp;' . $d['name'];
            } else {
                $d['name'] = '<i class="fa fa-circle" style="font-size: 13px;color: #7c858e
"></i>&ensp;' . $d['name'];
            }
        }
        $titles = ['管理员', '最后在线', '总在线时长'];
        return Tab::make()
            ->padding(0)
            ->add('业务信息',
                Callout::make('后台用户(最近登录)')->success() . Table::make($titles, $data)
            );
    }
   
//公共函数库增加 formatTime
/**
 * 将给定秒数转换为以“x天x时x分钟”形式
 * e.g. 123456 => 1天10时17分钟
 */
function  formatTime($seconds)
{
 $days  =  floor($seconds  /  86400);
 $hours  =  floor(($seconds  %  86400)  /  3600);
 $minutes  =  floor(($seconds  %  3600)  /  60);
 $result  =  "";
 
 if  ($days  >  0)  {
     $result  .=  "{$days}天";
 }
 
 if  ($hours  >  0)  {
     $result  .=  "{$hours}时";
 }
 
 if  ($minutes  >  0)  {
     $result  .=  "{$minutes}分钟";
 }
 return  $result;
}

看看效果:

用户时长统计.png


  • 上一条:
    在Laravel中构建业务流程模型
    下一条:
    lodash工具库
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在laravel中介绍一个生成假数据的PHP库:FakerPHP(0个评论)
    • 在laravel框架中对环境配置文件的加载过程步骤浅析(0个评论)
    • Laravel 10.12版本发布(0个评论)
    • 在laravel中以curl的方式请求京东联盟api获取数据流程步骤(0个评论)
    • 在Laravel中使用PHP内置服务器:PHP -S命令(0个评论)
    • 近期文章
    • 在go语言中以邮件标题中获取SPF和DMARC,来判断是否为垃圾邮件之垃圾邮件过滤器功能实现(0个评论)
    • 在go语言中使用attr字段标签提取XML属性数据示例(0个评论)
    • 在laravel中介绍一个生成假数据的PHP库:FakerPHP(0个评论)
    • 在laravel框架中对环境配置文件的加载过程步骤浅析(0个评论)
    • Laravel 10.12版本发布(0个评论)
    • 在go语言中如何记录每个HTTP请求到你的Web服务器、日志记录器?(0个评论)
    • 在Go语言中如何查找一个IP地址的网络地址?(0个评论)
    • ELK + Filebeat 搭建日志系统流程步骤(0个评论)
    • 在laravel中以curl的方式请求京东联盟api获取数据流程步骤(0个评论)
    • 在go语言中使用gin框架-中间件gin.BasicAuth()实现账号密码方式认证示例(0个评论)
    • 近期评论
    • 博主 在

      2023年国务院办公厅春节放假通知:1月21日起休7天中评论 @ xiaoB 你只管努力,剩下的叫给天意;天若有情天亦老,..
    • xiaoB 在

      2023年国务院办公厅春节放假通知:1月21日起休7天中评论 会不会春节放假后又阳一次?..
    • BUG4 在

      你翻墙过吗?国内使用vpn翻墙可能会被网警抓,你需了解的事中评论 不是吧?..
    • 博主 在

      go语言+beego框架中获取get,post请求的所有参数中评论 @ t1  直接在router.go文件中配就ok..
    • Jade 在

      如何在MySQL查询中获得当月记录中评论 Dear zongscan.com team, We can skyroc..
    • 2016-10
    • 2016-11
    • 2017-07
    • 2017-08
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-08
    • 2020-09
    • 2020-10
    • 2020-11
    • 2021-01
    • 2021-02
    • 2021-03
    • 2021-04
    • 2021-05
    • 2021-06
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-11
    • 2021-12
    • 2022-01
    • 2022-02
    • 2022-03
    • 2022-04
    • 2022-05
    • 2022-06
    • 2022-07
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客