对于使用 Laravel 和 MySQL 的 API,我们正在尝试使用 MySQL 触发器设置审核机制。 我们用类似
的东西扩展了
Illuminate\Database\DatabaseManager
public function connection($name = null)
{
$conn = parent::connection($name);
$conn->statement("SET @app_user_id=?", [Auth::user()->id ?? 'no_login']);
return $conn;
}
然后在
BEFORE UPDATE
触发器内,我们得到 @app_user_id
并设置 updated_by
。这似乎运行良好,有没有更好的方法来做到这一点,我们不想使用雄辩的模型事件,并且我们可以使用 MySQL 触发器,我们可能会遇到哪些可能的问题?示例:
@app_user_id
?DatabaseManager->connection()
被多次调用,而且在某些情况下我们根本不想设置 @app_user_id
,例如通过命令进行批量更新时。我们可以在中间件中设置 @app_user_id
,也许可以扩展 Illuminate\Auth\Middleware\Authenticate
而不丢失任何东西吗?稍后发生的数据库更新是否可能会使用未设置 @app_user_id
的不同连接?提前致谢,如果需要更多解释,请告诉我。
由于没有活动,我将回答我的问题。
使用触发器进行基本审核似乎是最好的选择,因为它以最少的代码更新涵盖了所有内容。
事实证明,Laravel 在整个请求过程中使用相同的连接(如预期),除非发生异常情况(断开连接或其他故障),因此我们决定扩展
Illuminate\Database\DatabaseManager
并覆盖 connect()
方法,并在那里设置 @app_user_id
。这在全球范围内都有效。为了在代码中启用/禁用,我们添加了另一个在触发器 SQL 中检查的变量 @audit_triggers_on
。
更“Laravel”的解决方案是在用户进行身份验证时使用事件来设置
@app_user_id
。在这种情况下,如果我们还想涵盖数据库故障的情况,则可以重写 reconnect()
方法。仅在需要时才调用该方法,即发生实际断开连接,并且只能在此时设置 @app_user_id
。但在实际情况下,这可能是不需要的,因为数据库在同一请求期间失败和恢复的可能性可能为零,因为我们正在讨论请求需要几秒钟的 Web 应用程序,而且许多实现无论如何都在数据库级别提供冗余。