本文目录导读:

在 PHP 中自动记录操作人信息,通常有几种实现方式,下面我会提供最实用、最安全的几种方案,并附上代码示例。
核心思路
- 获取当前用户:从 Session、JWT Token 或 API 密钥中识别用户
- 自动注入:利用框架中间件、魔术方法或 Trait 自动填充
- 记录字段:
created_by、updated_by、deleted_by(软删除时)
基于 Laravel 框架(最推荐)
使用 Trait 自动填充
创建一个 Trait,在模型的 creating 和 updating 事件中自动填充操作人。
<?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 + 过滤器 | 适合分布式 |
注意点
- 外键约束:建议设置
created_by等字段为可空,避免系统自动任务时报错 - 权限校验:记录操作人的同时,务必校验用户是否有操作权限
- 日志保留:大型系统建议定期归档日志
- 性能考虑:高频操作表可考虑异步写日志
最终推荐
如果使用 Laravel,强烈建议使用方案一(Trait),这是目前最主流且维护性最好的方式。
如果使用原生 PHP,建议封装一个 AuditService 类,统一管理操作人记录逻辑。
有任何特定框架或场景需求,欢迎告诉我,我可以提供更针对性的代码!
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播