Для добавления данных в БД MySQL применяется sql-команда INSERT, которая имеет следующий синтаксис:
INSERT INTO название_таблицы (столбец1, столбец2, столбецN) VALUES ( значение1, значение2, значениеN)
Данная команда также выполняется методом exec() объекта PDO. Стоит отметить, что для sql-команд
INSERT
, UPDATE
и DELETE
метод exec()
возвращает количество затронутных командой строк
(добавленных, измененных или удаленных). Таким образом, мы можем узнать сколько строк было добавлено.
Сначала рассмотрим простейшее добавление одного объекта в БД. Для примера возьмем созданную в прошлой теме базу данных "testdb1" и созданную в ней таблицу Users со следующим определением:
CREATE TABLE Users (id INTEGER AUTO_INCREMENT PRIMARY KEY, name VARCHAR(30), age INTEGER)
И для добавления определим следующий скрипт PHP:
<?php try { $conn = new PDO("mysql:host=localhost;dbname=testdb1", "root", "mypassword"); // SQL-выражение для добавления данных $sql = "INSERT INTO Users (name, age) VALUES ('Tom', 37)"; $affectedRowsNumber = $conn->exec($sql); echo "В таблицу Users добавлено строк: $affectedRowsNumber"; } catch (PDOException $e) { echo "Database error: " . $e->getMessage(); } ?>
Команда на добавление здесь выглядит следующим образом:
"INSERT INTO Users (name, age) VALUES ('Tom', 37)"
То есть в столбец name
добавляется строка "Tom", а в столбец age
- число 37. Для столбца id не добавляется никакого значения,
потому что при создании таблицы для него указан параметр AUTO_INCREMENT
- то есть значение этого столбца у каждой добавляемой строки
будет автоматически увеличиваеться по сравнению с предыдущей на единицу.
При добавлении мы получаем количество добавленных строк в переменую $affectedRowsNumber
и затем выводим ее значение в браузере. Поэтому
при успешном добавлении мы увидим
Также мы можем добавить сразу несколько объектов:
<?php try { $conn = new PDO("mysql:host=localhost;dbname=testdb1", "root", "mypassword"); $sql = "INSERT INTO Users (name, age) VALUES ('Sam', 41), ('Bob', 29), ('Alice', 32)"; $affectedRowsNumber = $conn->exec($sql); echo "В таблицу Users добавлено строк: $affectedRowsNumber"; } catch (PDOException $e) { echo "Database error: " . $e->getMessage(); } ?>
Здесь в таблицу добавляется три строки. Соответственно в браузере мы увидим:
В большинстве случаев добавляемые данные будут приходить из вне, например, присылаться в запросе пользователя. Рассмотрим добавление данных, отправленных из формы HTML. Для этого определим следующий скрипт:
<!DOCTYPE html> <html> <head> <title>METANIT.COM</title> <meta charset="utf-8" /> </head> <body> <?php if (isset($_POST["username"]) && isset($_POST["userage"])) { $username = $_POST["username"]; $userage = $_POST["userage"]; try { $conn = new PDO("mysql:host=localhost;dbname=testdb1", "root", "mypassword"); $sql = "INSERT INTO Users (name, age) VALUES ('$username', $userage)"; $affectedRowsNumber = $conn->exec($sql); // если добавлена как минимум одна строка if($affectedRowsNumber > 0 ){ echo "Data successfully added: name=$username age= $userage"; } } catch (PDOException $e) { echo "Database error: " . $e->getMessage(); } } ?> <h3>Create a new User</h3> <form method="post"> <p>User Name: <input type="text" name="username" /></p> <p>User Age: <input type="number" name="userage" /></p> <input type="submit" value="Save"> </form> </body> </html>
Здесь мы проверяем, пришли ли с сервера данные в POST-запросе, которые имеют ключи "username" и "userage":
if (isset($_POST["username"]) && isset($_POST["userage"])) {
Если эти данные имеются, то есть был отправлен post-запрос с данными на добавление, то мы получаем эти данные в переменные и добавляем их в бд.
$sql = "INSERT INTO Users (name, age) VALUES ('$username', $userage)";
Если была добавлена строка, то есть метод exec()
возвратил число больше нуля, то выводим пользователю соответствующее сообщение.
После кода php собственно определена форма на добавление данных с помощью post-запроса.
Запустим скрипт. Введем в форму данные и нажмем на кнопку:
И данные будут добавлены. Вроде все хорошо. Однако здесь есть большой недостаток.
Недостаток выше приведенного скрипа заключается в том, что мы никак не констролируем присылаемые данные и сохраняем их в базу данных как есть. Что
несет потенциальную угрозу безопасности, особенно при добавлении строк типа "; DELETE FROM `Users`; --
. Кроме того, в ряде случае может быть проблематично добавить даже безопасные данные, например, строку, которая содержит
одинарную кавычку, типа "Tom O'Brian".
Для решения этих проблем PDO предлагает параметризацию запросов с помощью применения заранее подготовленных выражений - prepared statement. Выражения prepared statement вместо жестко установленных значений или переменных принимают параметры, которые не привязаны к конкретным значениям. Эти выражения prepared statement посылаются серверу базы данных до того, как станут известны используемые данные, что позволяет серверу приготовить их к выполнению, но при этом они не выполняются. А когда пользователь присылает данные - параметры заменяются пришедшими данными, и выражение prepared statement выполняется.
Перепишем предыдущий пример с использованием параметров:
<!DOCTYPE html> <html> <head> <title>METANIT.COM</title> <meta charset="utf-8" /> </head> <body> <?php if (isset($_POST["username"]) && isset($_POST["userage"])) { try { $conn = new PDO("mysql:host=localhost;dbname=testdb1", "root", "mypassword"); $sql = "INSERT INTO Users (name, age) VALUES (:username, :userage)"; // определяем prepared statement $stmt = $conn->prepare($sql); // привязываем параметры к значениям $stmt->bindValue(":username", $_POST["username"]); $stmt->bindValue(":userage", $_POST["userage"]); // выполняем prepared statement $affectedRowsNumber = $stmt->execute(); // если добавлена как минимум одна строка if($affectedRowsNumber > 0 ){ echo "Data successfully added: name=" . $_POST["username"] ." age= " . $_POST["userage"]; } } catch (PDOException $e) { echo "Database error: " . $e->getMessage(); } } ?> <h3>Create a new User</h3> <form method="post"> <p>User Name: <input type="text" name="username" /></p> <p>User Age: <input type="number" name="userage" /></p> <input type="submit" value="Save"> </form> </body> </html>
В SQL-выражении теперь применяются параметры:
$sql = "INSERT INTO Users (name, age) VALUES (:username, :userage)";
:username
и :userage
- это названия параметров. Причем они начинаются с символа двоеточия :.
Само выражение prepared statement создается с помощью метода prepare() объекта PDO, в который передается выполняемая sql-команда:
$stmt = $conn->prepare($sql);
Фактически здесь создается объект PDOStatement, который сохраняется в переменную $stmt
.
Чтобы связать параметр с конкретным значением у объекта PDOStatement
вызывается метод bindValue(). Первый параметр этого метода -
собственно параметр из sql-команды, а второй параметр - передаваемое ему значение.
$stmt->bindValue(":username", $_POST["username"]);
Так, в данном случае параметр :username
привязывается к значению из $_POST["username"]
Причем привязка может производиться и к конкретным значениям и обычным переменным, например:
$user = "Tom" // привязка к переменной $user $stmt->bindValue(":username", $user);
Для выполнения sql-выражения у объекта PDOStatement
вызывается метод execute(), который для команды INSERT возвращает
число добавленных строк.
В примере выше для параметризации применялся метод bindValue():
$sql = "INSERT INTO Users (name, age) VALUES (:username, :userage)"; $stmt = $conn->prepare($sql); // привязываем параметры к значениям $stmt->bindValue(":username", $_POST["username"]); $stmt->bindValue(":userage", $_POST["userage"]); // выполняем prepared statement $affectedRowsNumber = $stmt->execute();
Но есть и другой способ привязки параметров к значениям - мы можем передать в метод execute() параметры и их значения в виде ассоциативного массива:
$sql = "INSERT INTO Users (name, age) VALUES (:username, :userage)"; $stmt = $conn->prepare($sql); // через массив передаем значения параметрам по имени $rowsNumber = $stmt->execute(array(":username" => $_POST["username"], ":userage" => $_POST["userage"]));
В этом случае названия параметров являются ключами.
Третий способ привязки значений к параметрам представляет передачу значений по позиции:
$sql = "INSERT INTO Users (name, age) VALUES (?, ?)"; $stmt = $conn->prepare($sql); // через массив передаем значения параметрам по позиции $rowsNumber = $stmt->execute(array($_POST["username"], $_POST["userage"]));
В этом случае вместо названий параметров применяются знаки вопроса ?. Для передачи этим параметрам значений в метод execute() также передается массив. Первое значение массива привязывается к первому параметру (условно добавляется вместо первого знака вопроса), второе значение привязывается ко второму параметру и т.д.