SQL查询可能由于多种原因而失败,即使同一查询之前运行了100次也没有问题。我想检测一下交易失败的天气。我发现了两种方法:
1:使用大量if else语句
$mysqli->begin_transaction();
$stmt = $mysqli->prepare("INSERT INTO testtable VALUES (?,?,?)");
if ( false===$stmt ) {
$mysqli->rollback();
issueInternalError();
}
$rc = $stmt->bind_param('iii', $x, $y, $z);
if ( false===$rc ) {
$mysqli->rollback();
issueInternalError();
}
$rc = $stmt->execute();
if ( false===$rc ) {
$mysqli->rollback();
issueInternalError();
}else{
$mysqli->commit();
}
$stmt->close();
2:在try catch块中执行查询
try{
$mysqli->begin_transaction();
$stmt = $mysqli->prepare("INSERT INTO testtable VALUES (?,?,?)");
$stmt->bind_param('iii', $x, $y, $z);
$stmt->execute();
$mysqli->commit();
}catch(Exception $e){
$mysqli->rollback();
issueInternalError();
}
使用try / catch将代码减半,并使其真正可读,但是第二个代码是否可以正确捕获所有可能的错误?或更完善的是,如果存在错误,将始终执行issueInternalError()
吗?
更新:
我已将此代码添加到php文件的开头
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
我在测试中得到的结果参差不齐:
已成功捕获此类错误:
$mysqli->begin_transaction();
$stmt = $mysqli->prepare("INSERT INTO testtable VALUES (?,?,?)");
$stmt->bind_param('iiissss', $x, $y, $z); //error here is successfully catched
但这不是
$mysqli->begin_transaction();
$stmt = $mysqli->prepare("INSERT INTO testtable VALUES (?,?,?)");
$stmt->bind_param('iii', $x, $y, $z,""); //error not catched
看起来第二个不是由mysqli引起的,因此不会引发。
答案 0 :(得分:1)
您的 try-catch 不会捕获所有错误。它只会捕获异常。 PHP 中的错误和异常是有区别的。
以下 try-catch 将仅捕获异常:
try {
// ...
} catch(Exception $e) {
// ...
}
要捕获异常和错误,您可以使用 Throwable
接口。作为旁注,最好始终为 PHP 中的类和接口提供完全指定的名称。
try {
// ...
} catch(\Throwable $e) {
// ...
}
Mysqli 可以抛出异常和错误。异常通常在mysqli 无法处理命令或MySQL 服务器端执行命令失败时触发。这些异常是 mysqli_sql_exception
异常类的实例。
如果 PHP 端有程序员错误,例如参数数量不正确或参数无效,那么 mysqli 将触发 PHP 错误。这些可能是各种错误,但通常,它们都源自基类 Error
。
警告:在 PHP 8 之前,许多错误只是警告。这些现在已经被正确分类。此外,在 mysqli 中修复了许多软件错误,这些错误在应该发生时不会触发异常。为获得最佳效果,请使用最新的 PHP 版本。