该方法返回一个 mysqli_warning 对象,允许遍历由数据库返回的所有警告。适用于那些执行成功但返回了 warning 的 SQL。
$mysqli = new mysqli("localhost", "user", "pass", "database");
$mysqli->query("YOUR SQL HERE");
if ($warning = $mysqli->get_warnings()) {
do {
echo "Warning: " . $warning->message . PHP_EOL;
} while ($warning->next());
}
相比之下,error_list 是一个包含所有错误信息的数组(包括 error code 和 message),适用于捕获失败的 SQL 执行信息。
$result = $mysqli->query("BROKEN SQL");
if (!$result) {
foreach ($mysqli->error_list as $error) {
echo "Error [{$error['errno']}]: {$error['error']}" . PHP_EOL;
}
}
为了实现更完整的日志记录,我们可以封装一个日志函数,同时记录错误与警告信息,并记录相关上下文(如 SQL 语句、执行时间、访问来源等),以便后续排查和优化。
function log_db_activity(mysqli $mysqli, string $sql, $result): void {
$log = [];
// 记录SQL语句
$log['sql'] = $sql;
$log['time'] = date('c');
// 检查错误
if (!$result && !empty($mysqli->error_list)) {
$log['errors'] = $mysqli->error_list;
}
// 检查警告
if ($warning = $mysqli->get_warnings()) {
$log['warnings'] = [];
do {
$log['warnings'][] = [
'errno' => $warning->errno,
'message' => $warning->message,
];
} while ($warning->next());
}
if (!empty($log['errors']) || !empty($log['warnings'])) {
// 可替换为数据库或持久化方式
file_put_contents(__DIR__ . '/db_log.json', json_encode($log, JSON_PRETTY_PRINT) . PHP_EOL, FILE_APPEND);
}
}
$mysqli = new mysqli("localhost", "user", "pass", "database");
$sql = "INSERT INTO users (id, name) VALUES (1, 'Tom')";
$result = $mysqli->query($sql);
log_db_activity($mysqli, $sql, $result);
MySQL 在执行一些可能导致索引失效的查询时会给出 warning,如:
$sql = "SELECT * FROM users WHERE name LIKE '%abc%'";
虽然这条 SQL 是合法且能返回结果的,但 get_warnings() 可揭示其效率问题,有利于优化索引或调整查询逻辑。
插入超过字段长度的内容时可能不会失败,但会触发警告。通过日志可及时发现并优化字段设计或前端校验逻辑。
在大型项目中,日志不应仅保存在本地文本中。你可以进一步将这些日志推送至如 https://gitbox.net/api/logs 的远程日志收集服务:
function send_log_to_remote(array $log): void {
$ch = curl_init('https://gitbox.net/api/logs');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode($log),
]);
curl_exec($ch);
curl_close($ch);
}