PHP 自动记录操作人信息

wen PHP项目 2

本文目录导读:

PHP 自动记录操作人信息

  1. 核心思路
  2. 方案一:基于 Laravel 框架(最推荐)
  3. 方案二:原生 PHP 全局函数
  4. 方案三:使用中间件(适合 REST API)
  5. 方案四:继承基类(面向对象)
  6. 高级技巧:自动记录操作日志
  7. 实战建议
  8. 最终推荐

在 PHP 中自动记录操作人信息,通常有几种实现方式,下面我会提供最实用、最安全的几种方案,并附上代码示例。

核心思路

  1. 获取当前用户:从 Session、JWT Token 或 API 密钥中识别用户
  2. 自动注入:利用框架中间件、魔术方法或 Trait 自动填充
  3. 记录字段created_byupdated_bydeleted_by(软删除时)

基于 Laravel 框架(最推荐)

使用 Trait 自动填充

创建一个 Trait,在模型的 creatingupdating 事件中自动填充操作人。

<?php
// app/Traits/Blameable.php
namespace App\Traits;
use Illuminate\Support\Facades\Auth;
trait Blameable
{
    public static function bootBlameable()
    {
        static::creating(function ($model) {
            if (Auth::check()) {
                $model->created_by = Auth::id();
            }
        });
        static::updating(function ($model) {
            if (Auth::check()) {
                $model->updated_by = Auth::id();
            }
        });
        // 可选:软删除记录操作人
        static::deleting(function ($model) {
            if (Auth::check() && !$model->isForceDeleting()) {
                $model->deleted_by = Auth::id();
                $model->save();
            }
        });
    }
}

在模型中使用

<?php
// app/Models/Post.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use App\Traits\Blameable;
class Post extends Model
{
    use Blameable;
    protected $fillable = ['title', 'content'];
    // 关联用户
    public function creator()
    {
        return $this->belongsTo(User::class, 'created_by');
    }
}

数据库迁移

Schema::create('posts', function (Blueprint $table) {
    $table->id();
    $table->string('title');
    $table->text('content');
    $table->unsignedBigInteger('created_by')->nullable();
    $table->unsignedBigInteger('updated_by')->nullable();
    $table->unsignedBigInteger('deleted_by')->nullable();
    $table->timestamps();
    $table->softDeletes();
});

原生 PHP 全局函数

如果不使用框架,可以通过全局函数或静态类实现。

<?php
// helpers.php
function getCurrentUser() {
    session_start(); // 确保 session 已启动
    return $_SESSION['user_id'] ?? null;
}
function autoRecord($model, $action = 'create') {
    $userId = getCurrentUser();
    switch ($action) {
        case 'create':
            $model->created_by = $userId;
            $model->updated_by = $userId;
            break;
        case 'update':
            $model->updated_by = $userId;
            break;
        case 'delete':
            $model->deleted_by = $userId;
            break;
    }
    return $model;
}

使用示例:

<?php
require 'helpers.php';
class Post {
    public $created_by;
    public $updated_by;
    public $deleted_by;
    public function save() {
        // 保存逻辑
        echo "保存成功,操作人ID: {$this->updated_by}\n";
    }
}
// 创建操作
$post = new Post();
$post->title = "Hello";
$post->content = "World";
autoRecord($post, 'create');
$post->save();
// 更新操作
autoRecord($post, 'update');
$post->save();

使用中间件(适合 REST API)

Symfony/其他框架示例

<?php
// Middleware/AuditMiddleware.php
class AuditMiddleware
{
    public function handle($request, $next)
    {
        // 获取当前用户
        $user = $this->getUserFromToken($request);
        // 将用户信息绑定到请求上下文
        $request->attributes->set('current_user_id', $user['id']);
        return $next($request);
    }
    private function getUserFromToken($request) {
        $token = $request->headers->get('Authorization');
        // 解析 JWT Token
        return json_decode(base64_decode($token), true);
    }
}

继承基类(面向对象)

<?php
// BaseModel.php
class BaseModel {
    protected $db;
    protected $currentUserId;
    public function __construct($userId = null) {
        $this->currentUserId = $userId ?? $this->getSessionUserId();
    }
    public function create($data) {
        $data['created_by'] = $this->currentUserId;
        $data['updated_by'] = $this->currentUserId;
        // 插入数据库
    }
    public function update($id, $data) {
        $data['updated_by'] = $this->currentUserId;
        // 更新数据库
    }
    public function softDelete($id) {
        $this->db->update(
            'your_table',
            ['deleted_by' => $this->currentUserId, 'deleted_at' => date('Y-m-d H:i:s')],
            "id = $id"
        );
    }
    private function getSessionUserId() {
        return $_SESSION['user_id'] ?? 0;
    }
}

高级技巧:自动记录操作日志

如果还需要记录完整的操作日志(什么时间、谁、做了什么),可以扩展:

trait AuditLoggable {
    protected static function bootAuditLoggable() {
        static::saved(function ($model) {
            // 检查是创建还是更新
            $action = $model->wasRecentlyCreated ? 'CREATE' : 'UPDATE';
            AuditLog::create([
                'user_id' => Auth::id(),
                'action' => $action,
                'table_name' => $model->getTable(),
                'record_id' => $model->id,
                'old_data' => json_encode($model->getOriginal()),
                'new_data' => json_encode($model->getAttributes()),
                'ip_address' => request()->ip(),
                'user_agent' => request()->userAgent(),
                'timestamp' => now(),
            ]);
        });
    }
}

实战建议

场景 推荐方案 说明
Laravel 项目 Trait + Event 最优雅,自动化程度高
原生 PHP 全局函数 简单直接
大型系统 中间件 + 日志系统 可追踪性强
微服务 JWT + 过滤器 适合分布式

注意点

  1. 外键约束:建议设置 created_by 等字段为可空,避免系统自动任务时报错
  2. 权限校验:记录操作人的同时,务必校验用户是否有操作权限
  3. 日志保留:大型系统建议定期归档日志
  4. 性能考虑:高频操作表可考虑异步写日志

最终推荐

如果使用 Laravel,强烈建议使用方案一(Trait),这是目前最主流且维护性最好的方式。

如果使用原生 PHP,建议封装一个 AuditService,统一管理操作人记录逻辑。

有任何特定框架或场景需求,欢迎告诉我,我可以提供更针对性的代码!

抱歉,评论功能暂时关闭!