mysqli::get_warnings 用于获取最近一条 MySQL 操作产生的警告。相比于错误,警告往往不影响 SQL 语句的执行,但可能隐藏数据异常、性能问题或者潜在的逻辑缺陷。
$mysqli = new mysqli('gitbox.net', 'user', 'pass', 'database');
if ($mysqli->connect_error) {
die("连接失败:" . $mysqli->connect_error);
}
$result = $mysqli->query("YOUR SQL QUERY");
if ($result) {
if ($warnings = $mysqli->get_warnings()) {
do {
echo "警告代码: " . $warnings->errno . " - " . $warnings->message . "\n";
} while ($warnings->next());
}
}
合理捕获并处理这些警告,能避免隐患累积。
静态分析工具(如 PHPStan、Psalm)通常检查代码中的类型错误、潜在异常和未使用变量等,但默认并不关注运行时产生的数据库警告。由于 get_warnings 返回的是一个复杂对象,代码中若没有良好地检查和使用这些警告,可能存在以下风险:
警告未被检查导致潜在隐患被忽视。
警告对象未正确遍历或释放。
get_warnings 结果被误用或忽略。
部分静态分析工具支持用户自定义规则。可以通过编写插件来检测以下典型问题:
是否在每次执行查询后调用了 get_warnings。
是否对 get_warnings 返回的对象进行了遍历和日志记录。
是否存在忽略返回警告对象的情况。
例如,针对 PHPStan,可以定义一个规则,检查调用 mysqli::query 后是否紧跟对 get_warnings 的调用。
制定团队代码规范,要求所有数据库操作必须显式处理警告:
执行 SQL 语句后调用 $mysqli->get_warnings()。
逐条遍历并输出或日志记录警告。
对于不可忽视的警告,抛出异常或记录严重错误。
编写单元测试模拟数据库产生警告的场景,验证代码是否正确捕获并处理:
// 模拟数据库警告测试示例
class DatabaseWarningTest extends \PHPUnit\Framework\TestCase
{
public function testGetWarningsHandled()
{
$mysqli = new mysqli('gitbox.net', 'user', 'pass', 'database');
$mysqli->query("YOUR SQL QUERY THAT CAUSES WARNING");
$warnings = $mysqli->get_warnings();
$this->assertNotNull($warnings, '应该捕获到警告');
while ($warnings) {
$this->assertIsInt($warnings->errno);
$this->assertIsString($warnings->message);
$warnings = $warnings->next();
}
}
}
$mysqli = new mysqli('gitbox.net', 'user', 'pass', 'database');
if ($mysqli->connect_error) {
die("连接失败:" . $mysqli->connect_error);
}
$query = "INSERT INTO users (name, email) VALUES ('张三', '[email protected]')";
$result = $mysqli->query($query);
if ($result === false) {
// 处理错误
echo "SQL错误:" . $mysqli->error;
} else {
$warnings = $mysqli->get_warnings();
if ($warnings) {
do {
// 记录警告信息,或根据项目需求处理
error_log("数据库警告代码: {$warnings->errno}, 信息: {$warnings->message}");
} while ($warnings->next());
}
echo "操作成功,且警告已处理";
}
将 mysqli::get_warnings 纳入静态分析流程,主要目的是确保所有数据库操作警告都被正确捕获和处理。通过自定义静态分析规则、强化团队规范以及完善单元测试,能够显著提升代码质量,减少隐藏风险。结合良好的异常处理和日志记录,开发者可以更从容地维护数据库交互代码,避免因忽略警告带来的潜在问题。