在 PHP 中构建准备好的语句时,我们是否需要测试 bind_param 的 return 值?

Do we need to test the return value of bind_param when building prepared statements in PHP?

相关问题是 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 的文档,它说明了 return 值:

Returns true on success or false on failure.

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

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

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

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

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', 'user', 'password', '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`, `gui-language`, `foreign-language-group-mode`, `version`) VALUES (?, ?, ?, ?)"))) {
    error_log($conn->error);
}
if (false === $stmt->bind_param('ssis', $mwblang, $guilang, $flgmode, $version)) {
    error_log($stmt->error);
}
if (false === $stmt->execute()) {
    error_log($stmt->error);
}

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