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納入靜態分析流程,主要目的是確保所有數據庫操作警告都被正確捕獲和處理。通過自定義靜態分析規則、強化團隊規範以及完善單元測試,能夠顯著提升代碼質量,減少隱藏風險。結合良好的異常處理和日誌記錄,開發者可以更從容地維護數據庫交互代碼,避免因忽略警告帶來的潛在問題。