在PHP中构建prepared statement时需要测试bind_param的返回值吗?

问题描述

链接的问题是 here

我已将链接问题中的代码升级为使用准备好的语句。

我现在有:

$stmt = $conn->prepare("INSERT INTO `workbook-data` (`workbook-language`,`gui-language`,`foreign-language-group-mode`,`version`) VALUES (?,?,?)");
$stmt->bind_param('ssis',$mwblang,$guilang,$flgmode,$version);

$mwblang = MysqLi_real_escape_string($conn,$_GET['mwblang']);
$guilang = MysqLi_real_escape_string($conn,$_GET['guilang']);
$flgmode = MysqLi_real_escape_string($conn,$_GET['flg']);
$version = MysqLi_real_escape_string($conn,$_GET['version'] ?? '210061');

if ($stmt->execute()) {
  echo "<br>" . "New record created successfully";
} else {
  echo "Error: " .  MysqLi_error($conn);
}

$stmt->close();

根据 bind_param 的文档,它说明了返回值:

成功返回真,失败返回假。

在这些官方示例中,他们似乎没有对失败进行任何错误检查。我们应该测试返回值吗?我已经为 execute() 这样做了,但我不确定需要多少检查。

解决方法

您不应该检查任何 mysqli 函数的返回值。这只是毫无意义。当您 enable proper mysqli error reporting 时,您会自动收到所有错误通知。

如果您出于某种奇怪的原因决定保持错误报告静音,那么您必须检查每个 mysqli 函数调用,包括 bind_param()。如果您确实检查了返回值,请确保永远不要在屏幕上显示错误消息。将错误记录到安全位置的文件中。

因此,您的代码应如下所示:

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$conn = new mysqli('localhost','user','password','test');
$conn->set_charset('utf8mb4'); // always set the charset

// ...

$stmt = $conn->prepare("INSERT INTO `workbook-data` (`workbook-language`,`gui-language`,`foreign-language-group-mode`,`version`) VALUES (?,?,?)");
$stmt->bind_param('ssis',$mwblang,$guilang,$flgmode,$version);
$stmt->execute();

或者像这样:

mysqli_report(MYSQLI_REPORT_OFF);
$conn = new mysqli('localhost','test');
if ($conn->connect_errno) {
    error_log($conn->connect_error);
}
if (false === $conn->set_charset('utf8mb4')) {
    error_log($conn->error);
}

// ...

if (false === ($stmt = $conn->prepare("INSERT INTO `workbook-data` (`workbook-language`,?)"))) {
    error_log($conn->error);
}
if (false === $stmt->bind_param('ssis',$version)) {
    error_log($stmt->error);
}
if (false === $stmt->execute()) {
    error_log($stmt->error);
}

请注意,根据您调用的函数,有 3 种不同的方式来读取错误消息。手动错误检查要详细得多。