首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

ThinkPHP 5 在線用戶檢測行為擴展:Session 同步、心跳更新、游客/會員雙模式

     編輯:PHP 綜合知識

核心設計目標

  • 自動維護 online 表,記錄用戶/游客最後活動時間
  • 定期清理超時記錄(默認 10 分鐘無活動視為離線)
  • 會員強制單點登錄:同一賬號僅允許一處在線
  • 行為擴展模式,零侵入業務控制器

1. 行為配置

<?php
// application/tags.php
return [
    'action_begin' => ['app\common\behavior\OnlineCheck'],
];

2. 行為類實現

<?php
// app/common/behavior/OnlineCheck.php
namespace app\common\behavior;

use think\facade\Session;
use think\facade\Config;
use think\facade\Db;

class OnlineCheck
{
    protected $options = [
        'ONLINE_CHECK'       => true,
        'ONLINE_CHECK_TIME'  => 10, // 分鐘
    ];

    public function run(&$params)
    {
        if (!Config::get('ONLINE_CHECK')) return;

        $onlineModel = Db::name('Online');
        $ipLong = ip2long(request()->ip());
        $now = time();
        $timeout = Config::get('ONLINE_CHECK_TIME') * 60;

        // 1. 清理過期記錄
        $onlineModel->where('lasttime', '<', $now - $timeout)->delete();

        // 2. 會員邏輯
        if (Session::has('login_account')) {
            // 更新心跳(每分鐘一次)
            if ($now - Session::get('access_time', 0) > 60) {
                Session::set('access_time', $now);
            }

            $uid = Session::get('login_uid');
            
            // 查找當前用戶在線記錄
            $record = $onlineModel->where(['uid' => $uid, 'lastip' => $ipLong])->find();
            
            if (!$record) {
                // 異地登錄或記錄丟失 → 強制下線
                Session::clear();
                return;
            }

            // 更新最後活動時間
            $onlineModel->where('id', $record['id'])
                        ->update(['lasttime' => $now, 'lastip' => $ipLong]);
        }
        // 3. 游客邏輯
        else {
            $record = $onlineModel->where('lastip', $ipLong)->find();
            
            if (!$record) {
                // 新游客
                $onlineModel->insert([
                    'uid'       => 0,
                    'account'   => 'Guest',
                    'nickname'  => '游客',
                    'lasttime'  => $now,
                    'lastip'    => $ipLong,
                ]);
            } else {
                $onlineModel->where('id', $record['id'])
                            ->update(['lasttime' => $now, 'lastip' => $ipLong]);
            }
        }
    }
}
?>

3. 數據表結構

CREATE TABLE `online` (
    `id`        INT UNSIGNED NOT NULL AUTO_INCREMENT,
    `uid`       INT UNSIGNED NOT NULL DEFAULT 0,
    `account`   VARCHAR(50)  NOT NULL DEFAULT '',
    `nickname`  VARCHAR(50)  NOT NULL DEFAULT '',
    `lasttime`  INT UNSIGNED NOT NULL DEFAULT 0,
    `lastip`    INT UNSIGNED NOT NULL DEFAULT 0,
    PRIMARY KEY (`id`),
    KEY `idx_uid_ip` (`uid`, `lastip`),
    KEY `idx_lasttime` (`lasttime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

4. 配置文件

<?php
// config/online.php
return [
    'ONLINE_CHECK'       => true,
    'ONLINE_CHECK_TIME'  => 10, // 分鐘
];

5. 後台展示在線用戶列表

<?php
// 控制器
public function onlineList()
{
    $list = Db::name('Online')
        ->where('lasttime', '>', time() - config('online.ONLINE_CHECK_TIME') * 60)
        ->order('lasttime DESC')
        ->paginate(20);
    
    foreach ($list as &$item) {
        $item['lastip'] = long2ip($item['lastip']);
        $item['lasttime'] = date('Y-m-d H:i:s', $item['lasttime']);
    }
    
    return view('', ['list' => $list]);
}
?>

6. 定時任務清理(可選,行為中已實時清理)

# crontab -e
*/5 * * * * /usr/bin/php /path/to/think online:clean
<?php
// application/command/Online.php
namespace app\command;

use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\facade\Db;
use think\facade\Config;

class Online extends Command
{
    protected function configure()
    {
        $this->setName('online:clean')
             ->setDescription('清理過期在線記錄');
    }

    public function execute(Input $input, Output $output)
    {
        $timeout = Config::get('online.ONLINE_CHECK_TIME') * 60;
        $deleted = Db::name('Online')
            ->where('lasttime', '<', time() - $timeout)
            ->delete();
        
        $output->writeln("清理過期在線記錄: {$deleted} 條");
        return 0;
    }
}
?>

關鍵點總結

場景處理邏輯
會員心跳每 60 秒更新一次 Session access_time,減少寫入
異地登錄online 表無記錄 → 清空 Session 強制下線
游客識別IP 長整型存儲,支持 IPv4
性能優化lasttime 索引 + 定期清理,表體積可控

擴展建議

  • 集成 think-worker 實現 WebSocket 實時在線狀態推送
  • 使用 Redis 存儲在線狀態,EXPIRE 自動過期,性能更強
  • 添加 User-Agent、地理位置字段豐富用戶畫像

行為擴展模式讓「在線檢測」成為橫切關注點,業務代碼零耦合,是 ThinkPHP 5 實現 AOP 的經典案例。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved