Инструменты пользователя

Инструменты сайта


software:development:web:docs:learn:mariadb:вatabase_creation_pdo

Различия

Показаны различия между двумя версиями страницы.

Ссылка на это сравнение

Следующая версия
Предыдущая версия
software:development:web:docs:learn:mariadb:вatabase_creation_pdo [2026/02/22 20:11] – создано VladPolskiysoftware:development:web:docs:learn:mariadb:вatabase_creation_pdo [2026/02/23 11:53] (текущий) – [Дополнения и Файлы] VladPolskiy
Строка 56: Строка 56:
 <note green> <note green>
 Connection failed: SQLSTATE[HY000] [1045] Access denied for user 'root'@'localhost' (using password: YES) Connection failed: SQLSTATE[HY000] [1045] Access denied for user 'root'@'localhost' (using password: YES)
 +</note>
 +<note shadow>
 +{{:software:development:web:docs:learn:mariadb:pdo_connect_db.php_9.png|}}
 </note> </note>
 ===== Установка режима вывода ошибок ===== ===== Установка режима вывода ошибок =====
Строка 66: Строка 69:
 <code sql connect_db.php> <code sql connect_db.php>
 try { try {
 +    // подключаемся к серверу
     $conn = new PDO("mysql:host=localhost", "root", "mypassword");     $conn = new PDO("mysql:host=localhost", "root", "mypassword");
     // установка режима вывода ошибок     // установка режима вывода ошибок
Строка 72: Строка 76:
 } }
 catch (PDOException $e) { catch (PDOException $e) {
-    echo "Connection failed: " . $e->getMessage();+    echo "Соединение не удалось: " . $e->getMessage();
 } }
 </code> </code>
 +
 +===== Закрытие подключения =====
 +После завершения работы скрипта PHP автоматически закрывает открытые подключения к базе данных. Но может потребоваться закрыть подключение еще в процессе работы скрипта. В этом случае объекту PDO можно присвоить значение null:
 +
 +<code sql SQL>
 +$conn = null;  // отключаемся от сервера базы данных
 +</code>
 +
 +===== Выполнение запросов в PDO. =====
 +==== Создание базы данных и таблиц ====
 +Для выполнения запросов к серверу базы данных у объекта PDO вызывается метод **%%exec()%%**, в который передается выполняемое выражение SQL.
 +<code sql SQL>
 +$conn = new PDO("mysql:host=localhost", "root", "mypassword");
 +$conn->exec(команда_sql);
 +</code>
 +=== Создание базы данных ===
 +Для создания базы данных применяется SQL-команда CREATE DATABASE, после которой указывается имя создаваемой базы данных.
 +
 +Создадим базу данных через PHP:
 +
 +<code sql create_db.php>
 +<?php
 + try {
 +    // подключаемся к серверу
 +    $conn = new PDO("mysql:host=localhost", "root", "");
 +     
 +    // SQL-выражение для создания базы данных
 +    $sql = "CREATE DATABASE blog";
 +    // выполняем SQL-выражение
 +    $conn->exec($sql);
 +    echo "Соединение с базой данных установлено";
 +}
 +catch (PDOException $e) {
 +    echo "Соединение не удалось: " . $e->getMessage();
 +}
 +?>
 +</code>
 +http://localhost/create_db.php
 +<note shadow>
 +{{:software:development:web:docs:learn:mariadb:pdo_create_db.php_8.png|}}
 +</note>
 +http://localhost/phpmyadmin/index.php?route=/server/databases
 +<note shadow>
 +{{:software:development:web:docs:learn:mariadb:pdo_create_db.php_9.png|}}
 +</note>
 +В данном случае после подключения к серверу определяется переменная $sql, которая хранит команду на создание бд с именем "blog":
 +<code sql SQL>
 +$sql = "CREATE DATABASE blog";
 +</code>
 +Далее для выполнения этой команды передаем ее в метод exec():
 +<code sql SQL>
 +$conn->exec($sql);
 +</code>
 +В итоге при успешном создании базы данных мы увидим в браузере сообщение об создании БД:
 +<note green>
 +База данных создана
 +</note>
 +=== Создание таблицы ===
 +Подобным образом можно выполнять запросы на создание таблиц в базе данных. Для создания таблиц применяется SQL-команда CREATE TABLE, после которой указывается имя создаваемой таблицы и в скобках определения столбцов.
 +
 +Так, возьмем выше созданную базу данных "blog". И создадим в ней таблицу, которая описывается следующим кодом
 +<code sql SQL>
 +<?php
 +CREATE TABLE Users (id INTEGER AUTO_INCREMENT PRIMARY KEY, name VARCHAR(30), pass VARCHAR(30), status VARCHAR(30));
 +?>
 +</code>
 +Здесь создается таблица под названием "users". Она будет хранить условных пользователей. В ней будет три столбца: id, name, pass и status. Столбец id представляет числовой уникальный идентификатор строки - или идентификатор пользователя. Столбец name представляет строку - имя пользователя. Столбец pass - соответственно пароль. А столбец status определяет, что это администратор, пользователь или гость.
 +
 +Для создания таблицы определим следующий скрипт php:
 +<code sql create_table_db.php>
 +<?php
 +try {
 +    // подключаемся к серверу
 +    $conn = new PDO("mysql:host=localhost;dbname=blog", "root", "");
 +     
 +    // SQL-выражение для создания таблицы
 +    $sql = "create table users (id integer auto_increment primary key, name varchar(30), pass varchar(30),status varchar(30));";
 +    // выполняем SQL-выражение
 +    $conn->exec($sql);
 +    echo "Создана таблица «Пользователи».";
 +}
 +catch (PDOException $e) {
 +    echo "Соединение не удалось: " . $e->getMessage();
 +}
 +?>
 +</code>
 +http://localhost/create_table_db.php
 +<note shadow>
 +{{:software:development:web:docs:learn:mariadb:pdo_create_table_db.php_9.png|}}
 +</note>
 +http://localhost/phpmyadmin/index.php?route=/sql&pos=0&db=blog&table=users
 +<note shadow>
 +{{:software:development:web:docs:learn:mariadb:pdo_create_table_db.php_10.png|}}
 +</note>
 +Обратите внимание, что по сравнению с предыдущим примером здесь в строке подключения указана база данных, в которой создается таблица: "mysql:host=localhost;dbname=blog"
 +
 +И после успешного выполнения запрос мы увидим в браузере сообщение об создании таблицы:
 +
 +<note green>Создана таблица «Пользователи».</note>
 +===== Добавление данных в PDO и параметризация запросов =====
 +Для добавления данных в БД MySQL применяется sql-команда INSERT, которая имеет следующий синтаксис:
 +<code sql SQL>
 +INSERT INTO название_таблицы (столбец1, столбец2, столбецN) VALUES ( значение1, значение2, значениеN)
 +</code>
 +Данная команда также выполняется методом **%%exec()%%** объекта PDO. Стоит отметить, что для sql-команд **%%INSERT, UPDATE и DELETE%%** метод exec() возвращает количество затронутных командой строк (добавленных, измененных или удаленных). Таким образом, мы можем узнать сколько строк было добавлено.
 +
 +Сначала рассмотрим простейшее добавление одного объекта в БД. Для примера возьмем созданную в прошлой теме базу данных "blog" и созданную в ней таблицу Users со следующим определением:
 +<code sql SQL>
 +CREATE TABLE Users (id INTEGER AUTO_INCREMENT PRIMARY KEY, name VARCHAR(30), pass VARCHAR(30), status VARCHAR(30));
 +</code>
 +И для добавления определим следующий скрипт PHP:
 +<code sql insert_user_db.php>
 +<?php
 +try {
 +    $conn = new PDO("mysql:host=localhost;dbname=blog", "root", "");
 +     
 +    // SQL-выражение для добавления данных
 +    $sql = "INSERT INTO Users (name, pass, status) VALUES ('eva', 123, 'admin')";
 +     
 +    $affectedRowsNumber = $conn->exec($sql);
 +    echo "В таблицу Users добавлено строк: $affectedRowsNumber";
 +}
 +catch (PDOException $e) {
 +    echo "Соединение не удалось: " . $e->getMessage();
 +}
 +?>
 +</code>
 +http://localhost/insert_user_db.php
 +<note shadow>
 +{{:software:development:web:docs:learn:mariadb:pdo_create_user_db.php_10.png|}}
 +</note>
 +http://localhost/phpmyadmin/index.php?route=/sql&pos=0&db=blog&table=users
 +<note shadow>
 +{{:software:development:web:docs:learn:mariadb:pdo_create_user_db.php_11.png|}}
 +</note>
 +Команда на добавление здесь выглядит следующим образом:
 +<code sql SQL>
 +$sql = "INSERT INTO Users (name, pass, status) VALUES ('eva', 123, 'admin')";
 +</code>
 +То есть в столбец **name** добавляется строка "**eva**", в **pass** - **123** а в столбец **status** - значение **admin**. Для столбца **%%id%%** не добавляется никакого значения, потому что при создании таблицы для него указан параметр **%%AUTO_INCREMENT%%** - то есть значение этого столбца у каждой добавляемой строки будет автоматически увеличиваеться по сравнению с предыдущей на единицу.
 +
 +При добавлении мы получаем количество добавленных строк в переменую **%%$affectedRowsNumber%%** и затем выводим ее значение в браузере. Поэтому при успешном добавлении мы увидим
 +
 +<note green>
 +В таблицу **Users** добавлено строк: 1
 +</note>
 +
 +=== Множественное добавление ===
 +Также мы можем добавить сразу несколько объектов:
 +<code sql insert_user_db.php>
 +<?php
 +try {
 +    $conn = new PDO("mysql:host=localhost;dbname=blog", "root", "");
 +     
 +    // SQL-выражение для добавления данных
 +    $sql = "INSERT INTO Users (name, age) VALUES ('Tom', 37)";
 +    $sql = "INSERT INTO Users (name, pass, status) VALUES ('eva', 123, 'admin')";
 +    $sql = "INSERT INTO Users (name, pass, status) VALUES
 +            ('tom', 456, 'admin'), 
 +            ('bob', 789, 'admin'), 
 +            ('alisa', 012, 'admin')";
 +     
 +    $affectedRowsNumber = $conn->exec($sql);
 +    echo "В таблицу Users добавлено строк: $affectedRowsNumber";
 +}
 +catch (PDOException $e) {
 +    echo "Соединение не удалось: " . $e->getMessage();
 +}
 +?>
 +</code>
 +http://localhost/phpmyadmin/index.php?route=/sql&pos=0&db=blog&table=users
 +<note shadow>
 +{{:software:development:web:docs:learn:mariadb:pdo_create_user_db.php_13.png|}}
 +</note>
 +Здесь в таблицу добавляется три строки. Соответственно в браузере мы увидим:
 +<note green>В таблицу Users добавлено строк: 3</note>
 +<note shadow>
 +{{:software:development:web:docs:learn:mariadb:pdo_create_user_db.php_12.png|}}
 +</note>
 +==== Добавление данных из формы HTML ====
 +В большинстве случаев добавляемые данные будут приходить из вне, например, присылаться в запросе пользователя. Рассмотрим добавление данных, отправленных из формы HTML. Для этого определим следующий скрипт:
 +<code php create_user_form.php>
 +<!DOCTYPE html>
 +<html>
 +<head>
 +<title>create_user_form.php</title>
 +<meta charset="utf-8" />
 +</head>
 +<body>
 +<?php
 +if (isset($_POST["username"]) && isset($_POST["userpass"])) {
 +     
 +    $username = $_POST["username"];
 +    $userpass = $_POST["userpass"];
 +    try {
 +        $conn = new PDO("mysql:host=localhost;dbname=blog", "root", "");
 +        $sql = "INSERT INTO Users (name, pass, status) VALUES ('$username', $userpass, 'user')";
 +        $affectedRowsNumber = $conn->exec($sql);
 +        // если добавлена как минимум одна строка
 +        if($affectedRowsNumber > 0 ){
 +            echo "Данные успешно добавлены: name=$username  pass= $userpass status= user";  
 +        }
 +    }
 +    catch (PDOException $e) {
 +        echo "Ошибка базы данных: " . $e->getMessage();
 +    }
 +}
 +?>
 +<h3>Создать нового пользователя</h3>
 +<form method="post">
 +    <p>Имя пользователя:
 +    <input type="text" name="username" /></p>
 +    <p>Пароль пользователя:
 +    <input type="number" name="userpass" /></p>
 +    <input type="submit" value="Создать">
 +</form>
 +</body>
 +</html>
 +</code>
 +http://localhost/create_user_form.php
 +<note shadow>
 +{{:software:development:web:docs:learn:mariadb:pdo_create_user_db.php_14.png|}}
 +</note>
 +http://localhost/phpmyadmin/index.php?route=/sql&pos=0&db=blog&table=users
 +<note shadow>
 +{{:software:development:web:docs:learn:mariadb:pdo_create_user_db.php_15.png|}}
 +</note>
 +Здесь мы проверяем, пришли ли с сервера данные в POST-запросе, которые имеют ключи **"username"** и **"userpass"**:
 +<code sql SQL>
 +if (isset($_POST["username"]) && isset($_POST["userpass"])) {
 +</code>
 +Если эти данные имеются, то есть был отправлен **post-запрос** с данными на добавление, то мы получаем эти данные, добавляем пользователю статус **"user"** в переменные и добавляем их в бд.
 +<code sql SQL>
 +$sql = "INSERT INTO Users (name, pass, status) VALUES ('$username', $userpass, 'user')";
 +</code>
 +Если была добавлена строка, то есть метод **%%exec()%%** возвратил число больше нуля, то выводим пользователю соответствующее сообщение.
 +
 +После кода php собственно определена форма на добавление данных с помощью **%%post%%**-запроса.
 +Здесь в таблицу добавляется новая строка строки. Соответственно в браузере мы увидим:
 +<note green>
 +Данные успешно добавлены: name=ivan pass= 654 status= user
 +</note>
 +<note shadow>
 +{{:software:development:web:docs:learn:mariadb:pdo_create_user_db.php_16.png|}}
 +</note>
 +==== Параметризация запросов ====
 +Недостаток выше приведенного скрипа заключается в том, что мы никак не констролируем присылаемые данные и сохраняем их в базу данных как есть. Что несет потенциальную угрозу безопасности, особенно при добавлении строк типа **%%"; DELETE FROM `Users`; --.%%** Кроме того, в ряде случае может быть проблематично добавить даже безопасные данные, например, строку, которая содержит одинарную кавычку, типа **%%"Tom O'Brian"%%**.\\  
 +Для решения этих проблем PDO предлагает параметризацию запросов с помощью применения заранее подготовленных выражений - **prepared statement**. Выражения **prepared statement** вместо жестко установленных значений или переменных принимают параметры, которые не привязаны к конкретным значениям. Эти выражения **prepared statement** посылаются серверу базы данных до того, как станут известны используемые данные, что позволяет серверу приготовить их к выполнению, но при этом они не выполняются. А когда пользователь присылает данные - параметры заменяются пришедшими данными, и выражение **prepared statement** выполняется.
 +
 +Перепишем предыдущий пример с использованием параметров:
 +<code sql create_user_form.php>
 +<!DOCTYPE html>
 +<html>
 +<head>
 +<title>create_user_form.php</title>
 +<meta charset="utf-8" />
 +</head>
 +<body>
 +<?php
 +if (isset($_POST["username"]) && isset($_POST["userpass"])) {
 +     
 +    try {
 +        $conn = new PDO("mysql:host=localhost;dbname=blog", "root", "");
 + $user = 'user';
 + $sql = "INSERT INTO Users (name, pass, status) VALUES (:username, :userpass, :user)";
 +        // определяем prepared statement
 +        $stmt = $conn->prepare($sql);
 +        // привязываем параметры к значениям
 +        $stmt->bindValue(":username", $_POST["username"]);
 +        $stmt->bindValue(":userpass", $_POST["userpass"]);
 + $stmt->bindValue(":user", $user);
 +        // выполняем prepared statement        
 +        $affectedRowsNumber = $stmt->execute();
 +        // если добавлена как минимум одна строка
 +        if($affectedRowsNumber > 0 ){
 +            echo "Данные успешно добавлены: name=" . $_POST["username"] ."  pass= " . $_POST["userpass"] . "status= user";  
 +        }
 +    }
 +    catch (PDOException $e) {
 +        echo "Database error: " . $e->getMessage();
 +    }
 +}
 +?>
 +<h3>Создать нового пользователя</h3>
 +<form method="post">
 +    <p>Имя пользователя:
 +    <input type="text" name="username" /></p>
 +    <p>Пароль пользователя:
 +    <input type="number" name="userpass" /></p>
 +    <input type="submit" value="Создать">
 +</form>
 +</body>
 +</html>
 +</code>
 +
 +<note shadow>
 +{{:software:development:web:docs:learn:mariadb:pdo_create_user_db.php_18.png|}}
 +</note>
 +В SQL-выражении теперь применяются параметры:
 +
 +<code sql SQL>
 +$sql = "INSERT INTO Users (name, pass, status) VALUES (:username, :userpass, :user)";
 +</code>
 +**%%:username%%** и **%%:userpass%%** - это названия параметров. Причем они начинаются с символа двоеточия **:**.
 +
 +Само выражение **prepared statement** создается с помощью метода **%%prepare()%%** объекта PDO, в который передается выполняемая sql-команда:
 +<code sql SQL>
 +$stmt = $conn->prepare($sql);
 +</code>
 +Фактически здесь создается объект **%%PDOStatement%%**, который сохраняется в переменную $stmt.
 +
 +Чтобы связать параметр с конкретным значением у объекта **%%PDOStatement%%** вызывается метод **%%bindValue()%%**. Первый параметр этого метода - собственно параметр из sql-команды, а второй параметр - передаваемое ему значение.
 +<code sql SQL>
 +$stmt->bindValue(":username", $_POST["username"]);
 +</code>
 +Так, в данном случае параметр **%%:username%%** привязывается к значению из **%%$_POST["username"]%%**
 +
 +Причем привязка может производиться и к конкретным значениям и обычным переменным, например:
 +<code sql SQL>
 +$user = "alexa"
 +// привязка к переменной $user
 +$stmt->bindValue(":username", $user);
 +</code>
 +Для выполнения sql-выражения у объекта PDOStatement вызывается метод **%%execute()%%**, который для команды **%%INSERT%%** возвращает число добавленных строк.
 +==== Передача значений параметрам через массив по имени ====
 +В примере выше для параметризации применялся метод **%%bindValue()%%**:
 +<code sql SQL>
 +$sql = "INSERT INTO Users (name, pass, status) VALUES (:username, :userpass, :user)";
 +// определяем prepared statement
 +$stmt = $conn->prepare($sql);
 +// привязываем параметры к значениям
 +$stmt->bindValue(":username", $_POST["username"]);
 +$stmt->bindValue(":userpass", $_POST["userpass"]);
 +$stmt->bindValue(":user", $user);
 +// выполняем prepared statement        
 +$affectedRowsNumber = $stmt->execute();
 +</code>
 +Но есть и другой способ привязки параметров к значениям - мы можем передать в метод **%%execute()%%** параметры и их значения в виде ассоциативного массива:
 +<code sql SQL>
 +$sql = "INSERT INTO Users (name, pass, status) VALUES (:username, :userpass, :user)";
 +$stmt = $conn->prepare($sql);
 +// через массив передаем значения параметрам по имени
 +$rowsNumber = $stmt->execute(array(":username" => $_POST["username"], ":userpass" => $_POST["userpass"], ":user" => $user));
 +</code>
 +В этом случае названия параметров являются ключами.
 +
 +==== Передача значений параметрам через массив по позиции ====
 +Третий способ привязки значений к параметрам представляет передачу значений по позиции:
 +<code sql SQL>
 +$sql = "INSERT INTO Users (name, pass, status) VALUES (?, ?, ?)";
 +// определяем prepared statement
 +$stmt = $conn->prepare($sql);
 +// привязываем параметры к значениям
 +$rowsNumber = $stmt->execute(array($_POST["username"], $_POST["userpass"], $user));
 +</code>
 +В этом случае вместо названий параметров применяются знаки вопроса **%%?%%**. Для передачи этим параметрам значений в метод **%%execute()%%** также передается массив. Первое значение массива привязывается к первому параметру (условно добавляется вместо первого знака вопроса), второе значение привязывается ко второму параметру и т.д.
 +===== Получение данных в PDO =====
 +
 +На уровне кода SQL получение данных осуществляется с помощью команды SELECT. Например, получение всех данных из таблицы Users:
 +<code sql SQL>
 +SELECT * FROM Users
 +</code>
 +В библиотеке pdo для получения данных у объекта PDO вызывается метод **%%query()%%**, в который передается команда SQL. Метод **%%query()%%** возвращает объект **%%PDOStatement%%**, который представляет набор всех полученных из базы данных строк.
 +<code sql SQL>
 +$sql = "SELECT * FROM Users";
 +$result = $conn->query($sql);
 +</code> 
 + Получив объект **%%PDOStatement%%**, мы можем извлечь данные. В частности, его метод fetch() при первом обращении первую строку (если в наборе есть строки):
 +<code sql SQL>
 +$row = $result->fetch();
 +</code> 
 +При последующих обращениях метод **%%fetch()%%** возвращает следующие строки, пока в наборе не останется строк. Если строк в наборе больше нет, то метод возвращает **%%false%%**. Поэтому для получения всех строк удобно использовать циклы. Например, цикл **%%while%%**:
 +<code sql SQL>
 +while($row = $result->fetch()){
 +    // обработка строк
 +}
 +</code> 
 +Таким образом, при каждой итерации цикл while будет получать новую строку из набора в переменную $row, пока метод $result->fetch() не возвратит false - после чего произойдет выход из цикла.
 +
 +Строка возвращается в виде ассоциативного массива, где отдельные значения - это столбцы строки, а ключи этих значений - названия столбцов таблицы. Например, получение значения столбца "name" в переменную:
 +<code sql SQL>
 +while($row = $result->fetch()){
 +    $username = $row["name"];
 +    // операции с $username
 +}
 +</code>
 +Вместо цикла **%%while%%** можно использовать цикл **%%for/foreach%%**. Например:
 +<code sql SQL>
 +foreach($result as $row){
 +    $username = $row["name"];
 +    // операции с $username
 +}
 +</code>
 +Здесь явным образом не вызывается метод **%%$result->fetch()%%**. Формально мы просто перебираем переменную $result как обычный массив, также помещая каждую строку в переменную $row.
 +
 +Теперь все объединим и получим данные из таблицы Users из прошлых тем, которая имеет следующее определение:
 +
 +<code sql select_user_form.php>
 +<?php
 +try {
 +    $conn = new PDO("mysql:host=localhost;dbname=blog", "root", "");
 +    $sql = "SELECT * FROM Users";
 +    $result = $conn->query($sql);
 +    echo "<table><tr><th>Id</th><th>Name</th><th>pass</th><th>status</th></tr>";
 +    while($row = $result->fetch()){
 +        echo "<tr>";
 +            echo "<td>" . $row["id"] . "</td>";
 +            echo "<td>" . $row["name"] . "</td>";
 +            echo "<td>" . $row["pass"] . "</td>";
 + echo "<td>" . $row["status"] . "</td>";
 +        echo "</tr>";
 +    }
 +    echo "</table>";
 +}
 +catch (PDOException $e) {
 +    echo "Ошибка базы данных: " . $e->getMessage();
 +}
 +?>
 +</code>
 +В данном случае полученные данные будут выводиться в таблицу, создаваемую элементом **%%<table>%%**:
 +\\  
 +http://localhost/select_user_form.php
 +<note shadow>
 +{{:software:development:web:docs:learn:mariadb:pdo_select_user_db.php_20.png|}}
 +</note>
 +
 +==== Фильтрация данных в PDO ====
 +В прошлой статье применялся метод query() для получения всех данных из БД. Но что, если нам надо получить не все, а какие-то определенные данные, которые овечают некоторому критерию, иными словами, произвести фильтрацию данных. Например, возьмем использовавшуюся в прошлых темах таблицу Users:
 +<code sql SQL>
 +CREATE TABLE Users (id INTEGER AUTO_INCREMENT PRIMARY KEY, name VARCHAR(30), pass VARCHAR(30),status VARCHAR(30))
 +</code>
 +Она имеет столбец id, и мы хотим получить определенный объект по id. На первый взгляд мы могли бы определить следующий код:
 +<code sql SQL>
 +$sql = "SELECT * FROM Users WHERE id = 1";
 +$result = $conn->query($sql);
 +</code>
 +Для фильтрации команде **%%SELECT%%** передается выражение **%%WHERE%%**, которая принимает названия столбцов их значения в качестве критерия фильтрации. То есть, здесь мы получаем строке, где **%%id = 1%%**.
 +
 +Однако если данные для фильтрации приходят извне, например, значение для столбца **%%id%%**, то опять же, как и в случае с добавлением, мы сталкиваемся с потенциальной уязвимостью кода. И также, как и при добавлении, в этом случае лучше использовать параметризацию и **%%prepared statements%%**.
 +
 +Например, мы хотим получать в **%%GET%%**-запросе значение для **%%id%%** и по нему получть из базы данных нужные данные. Определим для этого следующий скрипт **%%user.php%%**:
 +<code sql user.php>
 +<!DOCTYPE html>
 +<html>
 +<head>
 +<title>user.php</title>
 +<meta charset="utf-8" />
 +</head>
 +<body>
 +<?php
 +// зададим переменную для вывода строки
 +$_GET["id"] = 2;
 +if(isset($_GET["id"]))
 +{
 +    try {
 +        $conn = new PDO("mysql:host=localhost;dbname=blog", "root", "");
 +        $sql = "SELECT * FROM Users WHERE id = :userid";
 +        $stmt = $conn->prepare($sql);
 +        // привязываем значение параметра :userid к $_GET["id"]
 +        $stmt->bindValue(":userid", $_GET["id"]);
 +        // выполняем выражение и получаем пользователя по id
 +        $stmt->execute();
 +        if($stmt->rowCount() > 0){
 +            foreach ($stmt as $row) {
 +              $username = $row["name"];
 +              $userpass = $row["pass"];
 +              $userstatus = $row["status"];
 +              echo "<div>
 +                    <h3>Информация о пользователе</h3>
 +                    <p>Имя: $username</p>
 +                    <p>Пароль: $userpass</p>
 + <p>Статус: $userstatus</p>
 +                </div>";
 +            }
 +        }
 +        else{
 +            echo "Пользователь не найден";
 +        }
 +    }
 +    catch (PDOException $e) {
 +        echo "Соединение не удалось: " . $e->getMessage();
 +    }
 +}
 +?>
 +</body>
 +</html>
 +</code>
 +http://localhost/user.php
 +<note shadow>
 +{{:software:development:web:docs:learn:mariadb:pdo_select_user_db.php_21.png|}}
 +</note>
 +Для выполнения запроса к БД вначале создаем **%%prepared statement%%**, которое использует параметр userid, привязанный к значению **%%$_GET["id"]%%**:
 +<code sql SQL>
 +$sql = "SELECT * FROM Users WHERE id = :userid";
 +$stmt = $conn->prepare($sql);
 +$stmt->bindValue(":userid", $_GET["id"]);
 +</code>
 +Далее у полученного объекта **%%PDOStatement%%** вызываем метод **%%execute()%%**, который выполняет запрос к бд:
 +<code sql SQL>
 +$stmt->execute();
 +</code>
 +После выполнения команды **%%SELECT%%** этот объект содержит полученные из БД данные, которые мы можем перебрать с помощью цикла:
 +<code sql SQL>
 +if($stmt->rowCount() > 0){
 +    foreach ($stmt as $row) {
 +        $username = $row["name"];
 +        $userpass = $row["pass"];
 +        $userstatus = $row["status"];
 +    }
 +</code>
 +При этом с помощью метода **%%rowCount()%%** мы можем узнать количество возвращенных строк. Получение данных столбцов строки производится как и было описано выше для простого запроса **%%SELECT%%**. Получив данные столбцов в переменные, мы можем затем что-то с ними сделать, например, вывести их значения на страницу.\\  
 +Закоментируем явное определение **%%$_GET["id"] = 2;%%**
 +<note shadow>
 +{{:software:development:web:docs:learn:mariadb:pdo_select_user_db.php_25.png|}}
 +</note>
 +
 +Чтоб было проще обращаться к скрипту **%%user.php%%** и передавать ему **%%id%%**, определим скрипт **%%index_test.php%%**, который будет выводить список объектов:
 +<code php index_test.php>
 +<!DOCTYPE html>
 +<html>
 +<head>
 +<title>index_test.php</title>
 +<meta charset="utf-8" />
 +</head>
 +<body>
 +<h2>Список пользователей</h2>
 +<?php
 +try {
 +    $conn = new PDO("mysql:host=localhost;dbname=blog", "root", "");
 +    $sql = "SELECT id, name FROM Users";
 +    $result = $conn->query($sql);
 +    echo "<table><tr><th>Имя</th><th></th></tr>";
 +    foreach($result as $row){
 +        echo "<tr>";
 +            echo "<td>" . $row["name"] . "</td>";
 +            echo "<td><a href='user.php?id=" . $row["id"] . "' >Посмотреть</a></td>";
 +        echo "</tr>";
 +    }
 +    echo "</table>";
 +}
 +catch (PDOException $e) {
 +    echo "Ошибка базы данных: " . $e->getMessage();
 +}
 +?>
 +</body>
 +</html>
 +</code>
 +http://localhost/index_test.php
 +<note shadow>
 +{{:software:development:web:docs:learn:mariadb:pdo_select_user_db.php_22.png|}}
 +</note>
 +Здесь все объекты из базы данных выводятся в таблицу, где второй столбец содержит ссылку на скрипт **%%user.php%%**, которому передается соответствующее значение **%%id%%**. В итоге по нажатию на эту ссылку мы перейдем к описанию объекта по **%%id%%**:
 +<note shadow>
 +{{:software:development:web:docs:learn:mariadb:pdo_select_user_db.php_23.png|}}
 +</note>
 +Выведем значение, нажатием на ссылку
 +<note shadow>
 +{{:software:development:web:docs:learn:mariadb:pdo_select_user_db.php_26.png|}}
 +</note>
 +===== Обновление данных в PDO =====
 +Для обновления применяется **%%sql%%**-команда **%%UPDATE%%**:
 +<code sql SQL>
 +UPDATE Таблица
 +SET столбец1 = значение1, столбец2 = значение2,...
 +WHERE столбец = значение 
 +</code>
 +В библиотеке **%%pdo%%** для обновления данных может применяться тот же метод **%%exec()%%** объекта **%%PDO%%**, который применяется при добавлении. Например, возьмем использованную в прошлых темах таблицу **%%Users%%** со следующим определением:
 +<code sql SQL>
 +CREATE TABLE Users (id INTEGER AUTO_INCREMENT PRIMARY KEY, name VARCHAR(30), pass VARCHAR(30), status VARCHAR(30))
 +</code>
 +Изменим в этой таблице поле **%%pass%%** для строки, которая имеет **%%id = 11%%**:
 +<code sql update_user_db.php>
 +<?php
 +try {
 +    $conn = new PDO("mysql:host=localhost;dbname=blog", "root", "");
 +    $sql = "UPDATE Users SET pass = 777 WHERE id = 11";
 +    $affectedRowsNumber = $conn->exec($sql);
 +    echo "Обновлено строк: $affectedRowsNumber";
 +}
 +catch (PDOException $e) {
 +    echo "Database error: " . $e->getMessage();
 +}
 +?>
 +</code>
 +http://localhost/update_user_db.php
 +<note shadow>
 +{{:software:development:web:docs:learn:mariadb:pdo_update_user_db.php_27.png|}}
 +</note>
 +Результат метода $conn->exec() в данном случае количество обновленных строк.\\  
 +http://localhost/phpmyadmin/index.php?route=/sql&pos=0&db=blog&table=users
 +<note shadow>
 +{{:software:development:web:docs:learn:mariadb:pdo_update_user_db.php_28.png|}}
 +</note>
 +Однако если данные на обновление приходят извне, то мы опять как и при добавлении сталкиваемся с потенциальной уязвимостью подобного подхода. Поэтому в этом случаае опять же лучше использовать параметризацию и **%%prepared statements%%**.
 +
 +Отправка данных из формы и обновление
 +Сначала определим файл **%%index_test.php%%**, который будет выводить список пользователей:
 +<code php index_test.php>
 +<!DOCTYPE html>
 +<html>
 +<head>
 +<title>index_test.php</title>
 +<meta charset="utf-8" />
 +</head>
 +<body>
 +<h2>Список пользователей</h2>
 +<?php
 +try {
 +    $conn = new PDO("mysql:host=localhost;dbname=blog", "root", "");
 +    $sql = "SELECT * FROM Users";
 +    $result = $conn->query($sql);
 +    echo "<table><tr><th>Имя</th><th>Пароль</th><th></th></tr>";
 +    foreach($result as $row){
 +        echo "<tr>";
 +            echo "<td>" . $row["name"] . "</td>";
 +            echo "<td>" . $row["pass"] . "</td>";
 +            echo "<td><a href='update_user.php?id=" . $row["id"] . "'>Обновить</a></td>";
 +        echo "</tr>";
 +    }
 +    echo "</table>";
 +}
 +catch (PDOException $e) {
 +    echo "Ошибка базы данных: " . $e->getMessage();
 +}
 +?>
 +</body>
 +</html>
 +</code>
 +Здесь используется команда **%%SELECT%%**, которая получает всех пользователей из таблицы Users. В таблице третий столбец хранит ссылку на скрипт **%%update_user.php%%**, который мы далее создадим и которому передается параметр **%%id%%** с идентификатором пользователя, которого надо изменить.
 +
 +Теперь определим файл **%%update_user.php%%** для редактирования пользователей:
 +<code php update_user.php>
 +<?php 
 +try {
 +    $conn = new PDO("mysql:host=localhost;dbname=blog", "root", "");
 +}
 +catch (PDOException $e) {
 +    die("Database error: " . $e->getMessage());
 +}
 +?>
 +<!DOCTYPE html>
 +<html>
 +<head>
 +<title>update_user.php</title>
 +<meta charset="utf-8" />
 +</head>
 +<body>
 +<?php
 +// если запрос GET
 +if($_SERVER["REQUEST_METHOD"] === "GET" && isset($_GET["id"]))
 +{
 +    $userid = $_GET["id"];
 +    $sql = "SELECT * FROM Users WHERE id = :userid";
 +    $stmt = $conn->prepare($sql);
 +    $stmt->bindValue(":userid", $userid);
 +    // выполняем выражение и получаем пользователя по id
 +    $stmt->execute();
 +    if($stmt->rowCount() > 0){
 +        foreach ($stmt as $row) {
 +            $username = $row["name"];
 +            $userpass = $row["pass"];
 +            $userstatus = $row["status"];
 +        }
 +        echo "<h3>Обновление пользователя</h3>
 +                <form method='post'>
 +                    <input type='hidden' name='id' value='$userid' />
 +                    <p>Имя:
 +                    <input type='text' name='name' value='$username' /></p>
 +                    <p>Пароль:
 +                    <input type='text' name='pass' value='$userpass' /></p>
 +                    <p>Роль:
 +                    <input type='text' name='status' value='$userstatus' /></p>
 +                    <input type='submit' value='Сохранить' />
 +            </form>";
 +    }
 +    else{
 +        echo "Пользователь не найден";
 +    }
 +}
 +elseif (isset($_POST["id"]) && isset($_POST["name"]) && isset($_POST["pass"]) && isset($_POST["status"])) {
 +      
 +    $sql = "UPDATE Users SET name = :username, pass = :userpass, status = :userstatus WHERE id = :userid";
 +    $stmt = $conn->prepare($sql);
 +    $stmt->bindValue(":userid", $_POST["id"]);
 +    $stmt->bindValue(":username", $_POST["name"]);
 +    $stmt->bindValue(":userpass", $_POST["pass"]);
 +    $stmt->bindValue(":userstatus", $_POST["status"]);
 +          
 +    $stmt->execute();
 +    header("Location: index_test.php");
 +}
 +else{
 +    echo "Некорректные данные";
 +}
 +?>
 +</body>
 +</html>
 +</code>
 +http://localhost/index_test.php
 +<note shadow>
 +{{:software:development:web:docs:learn:mariadb:pdo_update_user_db.php_30.png|}}
 +</note>
 +При нажатии на кнопку **Обновить** браузер переместит нас на страницу обновления данных пользователя **update_user.php**
 +<note shadow>
 +{{:software:development:web:docs:learn:mariadb:pdo_update_user_db.php_31.png|}}
 +</note>
 +http://localhost/phpmyadmin/index.php?route=/sql&pos=0&db=blog&table=users
 +<note shadow>
 +{{:software:development:web:docs:learn:mariadb:pdo_update_user_db.php_32.png|}}
 +</note>
 +Весь код обновления структурно делится на две части. В первой части мы обрабатываем запрос **%%Get%%**. Когда пользователь нажимает на ссылку **%%"Обновить"%%** на странице **%%index_test.php%%**, то отправляется запрос **%%GET%%**, в котором передается **%%id%%** редактируемого пользователя. Поэтому мы сначала смотрим, представляет ли запрос **%%GET%%**-запрос и имеет ли он параметр **%%id%%**.
 +<code sql SQL>
 +if($_SERVER["REQUEST_METHOD"] === "GET" && isset($_GET["id"]))
 +</code>
 +И если это запрос **%%GET%%**, то нам надо вывести данные редактируемого пользователя в поля формы. Для этого отправляем базе данных запрос
 +<code sql SQL>
 +$sql = "SELECT * FROM Users WHERE id = :userid";
 +$stmt = $conn->prepare($sql);
 +$stmt->bindValue(":userid", $userid);
 +$stmt->execute();
 +</code>
 +Далее получаем полученные данные и, если они имеются, выводим их в поля формы. Таким образом, пользователь увидит на форме данные редактируемого объекта.
 +
 +Вторая часть скрипта представляет обработку **%%POST%%**-запроса - когда пользователь нажимает на кнопку на форме, то будет отправляться **%%POST%%**-запрос с отправленными данными. Мы получаем эти данные и отправляем базе данных команду **%%UPDATE%%** с этими данными, используя при этом параметризацию запроса:
 +<code sql SQL>
 +$sql = "UPDATE Users SET name = :username, pass = :userpass, status = :userstatus WHERE id = :userid";
 +$stmt = $conn->prepare($sql);
 +$stmt->bindValue(":userid", $_POST["id"]);
 +$stmt->bindValue(":username", $_POST["name"]);
 +$stmt->bindValue(":userpass", $_POST["pass"]);
 +$stmt->bindValue(":userstatus", $_POST["status"]);
 +$stmt->execute();
 +</code>
 +После выполнения запроса к БД перенаправляем пользователя на скрипт **index_test.php** с помощью 
 +функции
 +<code php update_user.php>
 +header("Location: index_test.php");
 +</code>
 +===== Удаление данных в PDO =====
 +Для удаления данных применяется sql-команда DELETE:
 +<code php delete_user.php>
 +DELETE FROM Таблица
 +WHERE столбец = значение
 +</code>
 +Для удаления данных также может применяться метод **%%exec()%%** объекта **PDO**. Например, возьмем использованную в прошлых темах таблицу Users со следующим определением:
 +<code sql SQL>
 +CREATE TABLE Users (id INTEGER AUTO_INCREMENT PRIMARY KEY, name VARCHAR(30), pass VARCHAR(30), STATUS VARCHAR(30))
 +</code>
 +Рассмотрим следующий пример удаления пользователя со значением **id = 5**
 +<code sql delete_user.php>
 +<?php
 +try {
 +    $conn = new PDO("mysql:host=localhost;dbname=blog", "root", "");
 +    $sql = "DELETE FROM Users WHERE id = 5";
 +    $affectedRowsNumber = $conn->exec($sql);
 +    echo "Удалено строк: $affectedRowsNumber";
 +}
 +catch (PDOException $e) {
 +    echo "Ошибка базы данных: " . $e->getMessage();
 +}
 +?>
 +</code>
 +Результат метода **%%$conn->exec()%%** в данном случае количество удаленых строк. Однако опять же поскольку значение столбца, на основе которого происходит удаление, нередко приходит извне, то в этом случае лучше использовать параметризацию.
 +\\  
 +
 +</code>
 +Итак, определим для вывода всех объектов из БД скрипт **index_test.php**:
 +<code php index_test.php>
 +<!DOCTYPE html>
 +<html>
 +<head>
 +<title>index_test.php</title>
 +<meta charset="utf-8" />
 +</head>
 +<body>
 +<h2>Список пользователей</h2>
 +<?php
 +try {
 +    $conn = new PDO("mysql:host=localhost;dbname=blog", "root", "");
 +    $sql = "SELECT * FROM Users";
 +    $result = $conn->query($sql);
 +    echo "<table><tr><th>Имя</th><th>Пароль</th><th></th></tr>";
 +    foreach($result as $row){
 +        echo "<tr>";
 +            echo "<td>" . $row["name"] . "</td>";
 +            echo "<td>" . $row["pass"] . "</td>";
 +            echo "<td><form action='delete_user.php' method='post'>
 +                        <input type='hidden' name='id' value='" . $row["id"] . "' />
 +                        <input type='submit' value='Удалить'>
 +                    </form></td>";
 +        echo "</tr>";
 +    }
 +    echo "</table>";
 +}
 +catch (PDOException $e) {
 +    echo "Ошибка базы данных: " . $e->getMessage();
 +}
 +?>
 +</body>
 +</html>
 +</code>
 +
 +В таблицы для каждой строки определена форма, которая посылает данные в **%%POST%%**-запросе скрипту **%%delete.php%%**. Чтобы передать в **%%delete.php%%** идентификатор удаляемого объекта, на форме определено скрытое поле для хранения **%%id%%** объекта.
 +
 +Обратите внимание, что в данном случае применяется не ссылка для удаления типа
 +
 +<code html exsample.html>
 +<a href="http://адрес_нашего_сайта/delete_user.php?id=1">Удалить<a/>
 +</code>
 +
 +которая оправляет данные в GET-запросе, а именно форма, которая отправляет данные в POST-запросе. Почему? Подобные GET-запросы потенциально небезопасны. Допустим, нам пришло электронное письмо, в которое была внедрена картинка посредством тега:
 +
 +<code html exsample.html>
 +<img src="http://адрес_нашего_сайта/delete_user.php?id=1" />
 +</code>
 +
 +В итоге при открытии письма 1-я запись в таблице может быть удалена. Уязвимость касается не только писем, но может проявляться и в других местах, но смысл один - **GET**-запрос к скрипту, который удаляет данные, несет потенциальную уязвимость.
 +
 +Теперь определим сам скрипт **delete_user.php**, который будет выполнять удаление:
 +<code sql delete_user.php>
 +<?php
 +if(isset($_POST["id"]))
 +{
 +    try {
 +    $conn = new PDO("mysql:host=localhost;dbname=blog", "root", "");
 +        $sql = "DELETE FROM Users WHERE id = :userid";
 +        $stmt = $conn->prepare($sql);
 +        $stmt->bindValue(":userid", $_POST["id"]);
 +        $stmt->execute();
 +        header("Location: index_test.php");
 +    }
 +    catch (PDOException $e) {
 +        echo "Ошибка базы данных: " . $e->getMessage();
 +    }
 +}
 +?>
 +</code>
 +В данном случае скрипт получает через POST-запрос значение id и по этому идентификатору выполняет удаление. После чего происходит переадресация на скрипт index_test.php.
 +\\  
 +http://localhost/index_test.php
 +<note shadow>
 +{{:software:development:web:docs:learn:mariadb:pdo_delete_user_db.php_35.png|}}
 +</note>
 +Результат работы скрипта, удаление записи 
 +<note shadow>
 +{{:software:development:web:docs:learn:mariadb:pdo_delete_user_db.php_37.png|}}
 +</note>
 +
 +
 +
 +
 +
 +===== Заключение =====
 +Изменим пути переадресации в файлах **delete_user** и **update_user** 
 +<code php exsample.php>
 +header("Location: setting_user.php");
 +</code>
 +Также добавим данный код в строку
 +<code php create_user_form.php>
 +        if($affectedRowsNumber > 0 ){
 +            echo "Данные успешно добавлены: name=$username  pass= $userpass status= user";
 +            header("Location: setting_user.php");
 +</code> 
 +И наконец создадим файл **setting_user** который будет объединять вышенаписанное в один файл управления пользователями
 +<code php setting_user.php>
 +<!DOCTYPE html>
 +<html>
 +<head>
 +<title>setting_user.php</title>
 +<meta charset="utf-8" />
 +</head>
 +<body>
 +<h2>Список пользователей</h2>
 +<?php
 + echo "<td><a href='create_user_form.php'>Добавить пользователя</a></td>";
 +try {
 +    $conn = new PDO("mysql:host=localhost;dbname=blog", "root", "");
 +    $sql = "SELECT * FROM Users";
 +    $result = $conn->query($sql);
 +    echo "<table><tr><th>id</th><th>Имя</th><th>Пароль</th><th>Роль</th></tr>";
 +    foreach($result as $row){
 +        echo "<tr>";
 + echo "<td>" . $row["id"] . "</td>";
 +            echo "<td>" . $row["name"] . "</td>";
 +            echo "<td>" . $row["pass"] . "</td>";
 + echo "<td>" . $row["status"] . "</td>";
 + echo "<td><a href='update_user.php?id=" . $row["id"] . "'>Обновить</a></td>";
 +            echo "<td><form action='delete_user.php' method='post'>
 +                        <input type='hidden' name='id' value='" . $row["id"] . "' />
 +                        <input type='submit' value='Удалить'>
 +                    </form></td>";
 +        echo "</tr>";
 +    }
 +    echo "</table>";
 +}
 +catch (PDOException $e) {
 +    echo "Ошибка базы данных: " . $e->getMessage();
 +}
 +?>
 +</body>
 +</html>
 +</code>
 +http://localhost/setting_user.php
 +<note shadow>
 +{{:software:development:web:docs:learn:mariadb:pdo_setting_user.php_40.png|}}
 +</note>
 +
 +===== Дополнения и Файлы =====
 +  * [[https://metanit.com/php/mysql/2.1.php|Ссылка на оригинальную статью]]
 +<note shadow>
 +{{ :software:development:web:docs:learn:mariadb:exsample_pdo_db_230226.rar |Файлы руководства}}
 +</note>
 +<note shadow>
 +{{ :software:development:web:docs:learn:mariadb:exsample_admin_panel_pdo_db_23.02.26.rar |Админ панель}}
 +</note>
software/development/web/docs/learn/mariadb/вatabase_creation_pdo.1771780267.txt.gz · Последнее изменение: VladPolskiy

Если не указано иное, содержимое этой вики предоставляется на условиях следующей лицензии: Public Domain
Public Domain Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki