Отчеты об ошибках подготовленных отчетов MySQLi [дубликат]
На этот вопрос уже есть ответ здесь:
Я пытаюсь разобраться в MySQli, и меня смущают сообщения об ошибках. Я использую возвращаемое значение инструкции MySQLi 'prepare' для обнаружения ошибок при выполнении SQL, например это:
$stmt_test = $mysqliDatabaseConnection->stmt_init();
if($stmt_test->prepare("INSERT INTO testtable VALUES (23,44,56)"))
{
$stmt_test->execute();
$stmt_test->close();
}
else echo("Statement failed: ". $stmt_test->error . "<br>");
Но разве возвращаемое значение инструкции prepare определяет только наличие ошибки в предварительной подготовке инструкции SQL и не обнаруживает ошибок выполнения? Если это так, то я должен изменить свою строку выполнения, чтобы также помечать ошибки следующим образом:
if($stmt_test->execute()) $errorflag=true;
А затем на всякий случай я также должен сделать следующее после выполнения инструкции:
if($stmt_test->errno) {$errorflag=true;}
...Или я был в порядке с самого начала, и возвращаемое значение в инструкции MySQLi prepare' фиксирует все ошибки связанный с полным выполнением запроса, который он определяет?
Спасибо C
3 answers
Я писал это дважды за последние два дня (так что для меня это дубликат, хотя вопросы начинались немного по-другому).
Каждый метод mysqli может завершиться неудачей. Вы должны проверить каждое возвращаемое значение. Если один из них потерпит неудачу, подумайте, имеет ли смысл продолжать работу с объектом, который находится не в том состоянии, в котором вы его ожидаете. (Потенциально не в "безопасном" состоянии, но я думаю, что здесь это не проблема.)
Так как только сообщение об ошибке для последней операции сохраняется в подключение/инструкция вы можете потерять информацию о , что вызвало ошибку, если вы продолжите после того, как что-то пошло не так. Возможно, вы захотите использовать эту информацию, чтобы позволить сценарию решить, следует ли повторить попытку (только временная проблема), что-то изменить или полностью выйти из игры (и сообщить об ошибке). И это значительно упрощает отладку.
$stmt = $mysqli->prepare("INSERT INTO testtable VALUES (?,?,?)");
// prepare() can fail because of syntax errors, missing privileges, ....
if ( false===$stmt ) {
// and since all the following operations need a valid/ready statement object
// it doesn't make sense to go on
// you might want to use a more sophisticated mechanism than die()
// but's it's only an example
die('prepare() failed: ' . htmlspecialchars($mysqli->error));
}
$rc = $stmt->bind_param('iii', $x, $y, $z);
// bind_param() can fail because the number of parameter doesn't match the placeholders in the statement
// or there's a type conflict(?), or ....
if ( false===$rc ) {
// again execute() is useless if you can't bind the parameters. Bail out somehow.
die('bind_param() failed: ' . htmlspecialchars($stmt->error));
}
$rc = $stmt->execute();
// execute() can fail for various reasons. And may it be as stupid as someone tripping over the network cable
// 2006 "server gone away" is always an option
if ( false===$rc ) {
die('execute() failed: ' . htmlspecialchars($stmt->error));
}
$stmt->close();
Редактировать: всего несколько заметок шесть лет спустя....
Расширение mysqli прекрасно способно сообщать об операциях, которые приводят к (mysqli) код ошибки, отличный от 0, с помощью исключений, см. mysqli_driver::$report_mode.
die() действительно, очень грубо, и я бы больше не использовал его даже для таких примеров, как этот.
Поэтому, пожалуйста, только уберите тот факт, что каждая операция (mysql) может завершиться неудачей по ряду причин; даже , если то же самое происходило тысячу раз раньше....
Полнота
Вам нужно проверить как $mysqli
, так и $statement
. Если они ложны, вам нужно вывести $mysqli->error
или $statement->error
соответственно.
Эффективность
Для простых сценариев, которые могут завершиться, я использую простые однострочные строки, которые вызывают ошибку PHP с сообщением. Для более сложного приложения вместо этого следует активировать систему предупреждения об ошибках, например, путем создания исключения.
Пример использования 1: Простой сценарий
# This is in a simple command line script
$mysqli = new mysqli('localhost', 'buzUser', 'buzPassword');
$q = "UPDATE foo SET bar=1";
($statement = $mysqli->prepare($q)) or trigger_error($mysqli->error, E_USER_ERROR);
$statement->execute() or trigger_error($statement->error, E_USER_ERROR);
Пример использования 2: Приложение
# This is part of an application
class FuzDatabaseException extends Exception {
}
class Foo {
public $mysqli;
public function __construct(mysqli $mysqli) {
$this->mysqli = $mysqli;
}
public function updateBar() {
$q = "UPDATE foo SET bar=1";
$statement = $this->mysqli->prepare($q);
if (!$statement) {
throw new FuzDatabaseException($mysqli->error);
}
if (!$statement->execute()) {
throw new FuzDatabaseException($statement->error);
}
}
}
$foo = new Foo(new mysqli('localhost','buzUser','buzPassword'));
try {
$foo->updateBar();
} catch (FuzDatabaseException $e)
$msg = $e->getMessage();
// Now send warning emails, write log
}
Не уверен, отвечает ли это на ваш вопрос или нет. Извините, если нет
Чтобы получить сообщение об ошибке из базы данных mysql о вашем запросе, вам нужно использовать объект подключения в качестве фокуса.
Итак:
echo $mysqliDatabaseConnection->error
Повторил бы ошибку, отправленную из mysql о вашем запросе.
Надеюсь, это поможет