#php #mysqli #prepared-statement
#php #mysql #mysqli #подготовленный оператор
Вопрос:
Я пробую подготовленные инструкции, но приведенный ниже код не работает. Я получаю сообщение об ошибке:
Неустранимая ошибка: вызов функции-члена execute() для не-объекта в /var/www/prepared.php в строке 12
<?php
$mysqli = new mysqli("localhost", "root", "root", "test");
if ($mysqli->connect_errno) {
echo "Failed to connect to MySQL: " . $mysqli->connect_error;
}
$stmt = $mysqli->prepare("INSERT INTO users (name, age) VALUES (?,?)");
// insert one row
$stmt->execute(array('one',1));
// insert another row with different values
$stmt->execute(array('two',1));
?>
Кроме того, нужно ли мне использовать mysqli для подготовленных инструкций? Может кто-нибудь указать мне на полный пример подготовленных инструкций от подключения до вставки до выбора с обработкой ошибок?
Комментарии:
1. «Может ли кто-нибудь указать мне на полный пример подготовленного оператора от подключения до вставки до выбора с обработкой ошибок» Да. php.net/manual/en/mysqli.prepare.php . Обратите внимание на строку »
mysqli_prepare()
возвращает объект инструкции илиFALSE
если произошла ошибка.» .
Ответ №1:
Из mysqli::prepare
документации:
Маркеры параметров должны быть привязаны к переменным приложения с помощью mysqli_stmt_bind_param() и / или mysqli_stmt_bind_result() перед выполнением инструкции или извлечением строк.
т.е.:
$name = 'one';
$age = 1;
$stmt = $mysqli->prepare("INSERT INTO users (name, age) VALUES (?,?)");
// bind parameters. I'm guessing 'string' amp; 'integer', but read documentation.
$stmt->bind_param('si', $name, $age);
// *now* we can execute
$stmt->execute();
Ответ №2:
Также мне нужно использовать mysqli для подготовленного оператора. Может кто-нибудь указать мне на полный пример подготовленного оператора от подключения до вставки до выбора с обработкой ошибок
Вы также можете использовать PDO, который я предпочитаю. На самом деле, похоже, что вы путаете PDO и Mysqli в своем примере кода.
$db = new PDO($dsn, $user, $pass);
$stmt = $db->prepare("INSERT INTO users (name, age) VALUES (?,?)");
$stmt->execute(array($name1, $age1));
$stmt->execute(array($name2, $age2));
В отличие от mysqli вам не нужно вызывать отдельную функцию привязки, хотя эта функция доступна, если вы предпочитаете / хотите / должны ее использовать.
Еще одна интересная особенность PDO — это именованные заполнители, которые могут быть гораздо менее запутанными в сложных запросах:
$db = new PDO($dsn, $user, $pass);
$stmt = $db->prepare("INSERT INTO users (name, age) VALUES (:name,:age)");
$stmt->execute(array(':name' => $name1, ':age' => $age1));
$stmt->execute(array(':name' => $name2, ':age' => $age2));
Ответ №3:
Подключение
Важность соединения mysqli часто упускается из виду, сводясь к одной строке. В то время как правильный код подключения может решить множество проблем, от безопасности до удобства использования.
Учитывая, что ваш код является обычным процедурным PHP, вот простой код подключения mysqli, который будет включен в ваши скрипты:
$host = '127.0.0.1';
$db = 'test';
$user = 'root';
$pass = '';
$charset = 'utf8mb4';
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
try {
$mysqli = new mysqli($host, $user, $pass, $db);
$mysqli->set_charset($charset);
} catch (mysqli_sql_exception $e) {
throw new mysqli_sql_exception($e->getMessage(), $e->getCode());
}
unset($host, $db, $user, $pass, $charset); // we don't need them anymore
Полное объяснение можно найти в моей статье Как правильно подключиться с помощью mysqli (а также множество полезных советов), но только небольшая цитата, чтобы выделить наиболее важные части:
- установка правильного набора символов для соединения устранит целый класс ошибок, таких как странные символы / вопросительные знаки вместо ваших данных, пустой вывод json_encode(), проблемы с сохранением смайликов и т. Д.
- установка правильного режима сообщения об ошибках устранит загадочные сообщения об ошибках, такие как ожидаемый параметр mysqli_fetch_assoc()… / Вызов функции-члена bind_param() …, вместо этого выдает фактическое сообщение об ошибке от MySQL.
- безопасность — это не повод для смеха, не должно быть возможности утечки данных вашей базы данных наружу
Вставка
Вставить запрос относительно прост, и он уже рассмотрен в другом ответе.
Все, что вам нужно, это заменить все переменные (вместе с окружающими кавычками!) в запросе вопросительными знаками, затем подготовить запрос, затем вставить все переменные с их типами bind_param()
и, наконец, выполнить запрос.
Только небольшой совет: MySQL с радостью примет все переменные в виде строк, поэтому не сходите с ума, находя правильный тип для определенной переменной, просто используя «s» для любой.
Итак, в основном вставка будет выглядеть так
$sql = "INSERT INTO users (name, email, password) VALUES (?,?,?)";
$stmt= $conn->prepare($sql);
$stmt->bind_param("sss", $name, $email, $password_hash);
$stmt->execute();
Тот же принцип следует использовать для всех других типов запросов, таких как ОБНОВЛЕНИЕ или УДАЛЕНИЕ.
Выбор
Выполнение запроса select почти то же самое, но с одной маленькой хитростью. По какой-то неизвестной причине вы не можете использовать знакомые функции выборки сразу из подготовленного оператора. Итак, сначала вам нужно получить mysqli_result, а затем вы сможете использовать fetch_assoc()
и т. fetch_obj()
Д:
$sql = "SELECT * FROM users WHERE id=?"; // SQL with parameters
$stmt = $conn->prepare($sql);
$stmt->bind_param("s", $id);
$stmt->execute();
$result = $stmt->get_result(); // get the mysqli result
$user = $result->fetch_assoc(); // fetch data
Совет: нет абсолютно никакой необходимости в знакомой mysqli_num_rows()
функции. Если вы подумаете об этом, вы всегда можете использовать сами данные, чтобы узнать, вернул ли ваш запрос какие-либо строки:
$user = $result->fetch_assoc();
if ($user) {
// found!
}
то же самое касается нескольких строк, благодаря
еще один совет: есть удобная функция fetch_all()
, которая может получить массив всех выбранных строк за один раз. Например, если запрос возвращает несколько строк, вы можете преобразовать их в массив, изменив последнюю строку на
$users = $result->fetch_all(MYSQLI_ASSOC); // fetch data
Обработка ошибок
Обработка ошибок — самая важная, но несколько неожиданная часть. Несмотря на то, что говорится в многочисленных статьях и примерах, как правило, вам вообще не следует писать код для обработки ошибок. Это звучит абсолютно безумно, но именно так все и должно быть сделано. Большую часть времени все, что вам нужно сделать, это просто сообщить об ошибке. И mysqli / PHP уже может сделать это за вас, помощь не требуется. Поэтому вам не следует писать какой-либо код, который проверяет результат выполнения запроса — в случае ошибки mysqli сообщит об этом автоматически, благодаря mysqli_report()
вызову функции, упомянутому в части #Connection . Опять же, полное объяснение этого принципа можно найти в другой статье, посвященной общим отчетам об ошибках PHP.
В редких случаях, когда вам действительно нужно обработать ошибку, то есть выполнить какое-то действие в случае ошибки, а не просто сообщить об этом, затем оберните ваши запросы в a try..catch
.