Что такое PDO или расширение для работы с MySQL

Рассмотрим расширение для PHP под названием PDO, что это такое и как нам работать с этим расширением. Вкратце, PDO (PHP Data Objects) – это некая прослойка в виде универсального способа работы с базами данных.

PDO в MySQL
PDO в MySQL

Настройка параметров PDO

Перед подключением к серверу баз данных MySQL необходимо иметь:

  1. Сервер базы данных MySQL, базу данных и учетную запись, имеющую доступ к базе данных.
  2. Драйвер PDO MySQL, включенный в файле php.ini сервера.

Предположим, что у вас есть локальный сервер базы данных MySQL, который содержит следующую информацию:

  • Хостом является localhost.
  • База данных на локальном сервере баз данных называется bookdb.
  • Учетную запись с пользователем root и паролем 'S@cr@t1!', которая может получить доступ к базе данных bookdb.

В большинстве случаев в качестве локального сервера многие программисты используют OpenServer (сайт — ospanel.io/download). Я также использую этот сервер на своем ноутбуке на Windows 10. Очень классный сервер и если вы будете его использовать — не поленитесь задонатить автору проекта.

В PHP мы можем создать файл config.php и разместить в нем параметры базы данных:

<?php

$host = 'localhost';
$db = 'bookdb';
$user = 'root';
$password = 'S@cr@t1!';

Чтобы использовать параметры базы данных, мы можем включить файл config.php с помощью конструкции require в любой php-файл на сервере:

<?php

require 'config.php';

Включение драйвера PDO_MySQL

PDO_MYSQL — это драйвер, реализующий интерфейс PDO. PDO использует драйвер PDO_MYSQL для подключения к базе данных MySQL.

Чтобы проверить, включен ли драйвер PDO_MYSQL, откройте файл php.ini. Файл php.ini часто находится в каталоге php. Например, вы можете найти файл php.ini в каталоге C:\xampp\php, если вы используете XAMPP под Windows.

Кроме того, различные версии PHP вы можете скачать с официального сайта на этой странице.

Ниже показана строка расширения в файле php.ini:

;extension=php_pdo_mysql.dll

Чтобы включить расширение, вам нужно раскомментировать его, удалив точку с запятой (;) из начала строки следующим образом:

extension=php_pdo_mysql.dll

После этого необходимо перезапустить веб-сервер, чтобы изменения вступили в силу.

Имя источника данных MySQL или DSN

PDO использует имя источника данных (DSN), которое содержит следующую информацию:

  • хост сервера базы данных
  • имя базы данных
  • имя пользователя
  • пароль для доступа к БД
  • другие параметры, такие как наборы символов и т. д.

PDO использует эту информацию для установления соединения с сервером базы данных. Для подключения к серверу базы данных MySQL используется следующий формат имени источника данных:

"mysql:host=host_name;dbname=db_name;charset=UTF8"

Например:

$dsn = "mysql:host=localhost;dbname=bookdb;charset=UTF8";
Обратите внимание, что charset UTF-8 устанавливает набор символов соединения с базой данных в UTF-8.

Создание БД

Сначала войдите на сервер баз данных MySQL под пользователем root из командной строки в Windows или терминала в macOS и Linux:

mysql -u root

И вам будет предложено ввести пароль; введите пароль для пользователя root, и вы подключены к серверу MySQL.

Далее создайте базу данных bookdb, выполнив следующий запрос CREATE DATABASE:

CREATE DATABASE IF NOT EXISTS bookdb;

Затем выберем нужную нам базу данных bookdb:

USE bookdb;

После этого выполните следующий запрос CREATE TABLE для создания таблицы publishers:

CREATE TABLE IF NOT EXISTS publishers (
    publisher_id INT AUTO_INCREMENT,
    name VARCHAR(255) NOT NULL,
    PRIMARY KEY (publisher_id)
);

Наконец, выполните следующий запрос CREATE TABLE для создания таблицы books:

CREATE TABLE IF NOT EXISTS books (
    book_id INT AUTO_INCREMENT,
    title VARCHAR(255) NOT NULL,
    isbn VARCHAR(13) NULL,
    published_date DATE NULL,
    publisher_id INT NULL,
    PRIMARY KEY (book_id),
    CONSTRAINT fk_publisher FOREIGN KEY (publisher_id)
        REFERENCES publishers (publisher_id)
);

Подключение к БД

Другой метод, использующий PHP-скрипт для подключения к MySQL — это использование PDO. Этот метод похоже на предыдущий, но с небольшими изменениями:

1. В public_html создайте файл с именем pdoconfig.php и вставьте следующий код. Как всегда, не забудьте заменить значения переменных на информацию из вашей базы данных. Сохраните и закройте файл, как только закончите.

<?php
    $host = 'localhost';
    $dbname = 'databasename';
    $username = 'username';
    $password = 'password';

2. Создайте другой файл под названием databaseaseconnect.php в том же каталоге, но с кодом ниже. Если вы назвали предыдущий файл по-другому, убедитесь, что изменили значение required_once.

<?php
require_once 'pdoconfig.php';
 
try {
    $conn = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
    echo "Connected to $dbname at $host successfully.";
} catch (PDOException $pe) {
    die("Could not connect to the database $dbname :" . $pe->getMessage());
}

Подключение к базе данных PDO требует создания нового объекта PDO с именем источника данных (DSN — Data Source Name), именем пользователя (username) и паролем (password).

DSN определяет тип базы данных, имя базы данных и при необходимости любую другую информацию, связанную с базой данных. Это переменные и значения, которые мы указали в файле dbconfig.php, на которые однажды была сделана ссылка строкой require_once в databaseaseconnect.php.

В последнем вы найдете код trycatch … Это означает, что сценарий попытается подключиться к MySQL, используя предоставленный код, но в случае возникновения проблемы будет выполнен код в разделе catch. Вы можете использовать блок catch для отображения сообщений об ошибках подключения или запустить альтернативный код, если блок try не работает.

Если соединение установлено успешно, он выведет сообщение «Подключено к $dbname на $host успешно». Однако, если попытка не удалась, код перехвата покажет простое сообщение об ошибке и завершит сценарий.

Следующий сценарий index.php иллюстрирует, как подключиться к базе данных bookdb на сервере баз данных MySQL с учетной записью root:

<?php

require 'config.php'; // подключение файла с данными от БД

$dsn = "mysql:host=$host;dbname=$db;charset=UTF8";

try {
	$pdo = new PDO($dsn, $user, $password);

	if ($pdo) {
		echo "Соединение с базой $db успешно!";
	}
} catch (PDOException $e) {
	echo $e->getMessage();
}

Как это работает.

Сначала создаем новый объект PDO с именем источника данных, пользователем и паролем. Объект PDO является экземпляром класса PDO.

Далее, выводим сообщение об успешном соединении с БД, если соединение установлено успешно, или сообщение об ошибке, если произошла ошибка соединения.

Если у вас все настроено правильно, вы увидите следующее сообщение:

Соединение с базой bookdb успешно!

Итак! Давайте еще раз кратко.

Сначала создаем файл config.php для хранения параметров базы данных:

<?php

$host     = 'localhost';
$db       = 'bookdb';
$user     = 'root';
$password = '';

Далее, создаем новый файл connect.php, который подключается к базе данных bookdb:

<?php

require 'config.php';

$dsn = "mysql:host=$host;dbname=$db;charset=UTF8";

try {
	$options = [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION];

	$conn = new PDO($dsn, $user, $password, $options);

	if ($conn) {
		echo "Connected to the $db database successfully!";
	}
} catch (PDOException $e) {
	echo $e->getMessage();
}

Чтобы сделать этот процесс более удобным для повторного использования, вы можете определить функцию с именем connect(), которая возвращает новое соединение с базой данных и возвращает его из файла connect.php:

<?php

require_once 'config.php';

function connect($host, $db, $user, $password)
{
	$dsn = "mysql:host=$host;dbname=$db;charset=UTF8";

	try {
		$options = [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION];

		return new PDO($dsn, $user, $password, $options);
	} catch (PDOException $e) {
		die($e->getMessage());
	}
}

return connect($host, $db, $user, $password);

Чтобы подключиться к базе данных в других файлах, вы используете конструкцию require следующим образом:

<?php

$pdo = require 'connect.php';

var_dump($pdo);

Конструкция require загружает файл connect.php и возвращает новый экземпляр PDO, возвращенный функцией connect().

Подход ООП для PDO

Рассмотрим использование подхода на основе классов Объектно-Ориентированного Программирования (ООП).

Чтобы использовать класс вместо функции для создания нового соединения с базой данных, нужно выполнить несколько шагов.

Во-первых, создайте новый файл с именем Connection.php и определите класс Connection:

<?php

require_once 'config.php';

class Connection
{
	public static function make($host, $db, $user, $password)
	{
		$dsn = "mysql:host=$host;dbname=$db;charset=UTF8";

		try {
			$options = [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION];

			return new PDO($dsn, $username, $password, $options);
		} catch (PDOException $e) {
			die($e->getMessage());
		}
	}
}

return Connection::make($host, $db, $user, $password);

Класс Connection имеет метод make(), который возвращает новый экземпляр PDO.

Во-вторых, используйте файл Connection.php в других файлах сценариев следующим образом:

<?php

$pdo = require 'Connection.php';
var_dump($pdo);

Мы создали базу данных bookdb на сервере MySQL и разработали повторно используемый скрипт для подключения к базе данных.

Подготовленные запросы PDO

Рассмотрим теперь подготовленные запросы PDO и то, как эффективно их использовать.

Подготовленный запрос — это шаблон для выполнения одного или нескольких SQL-запросов с различными значениями. Подготовленный оператор является высокоэффективным и помогает защитить приложение от SQL-инъекций.

Когда сервер базы данных выполняет запрос, он проходит два основных этапа: подготовка и выполнение.

Подготовка — сервер базы данных проверяет синтаксис SQL-запроса и инициализирует внутренние ресурсы сервера для этапа выполнения.

Выполнение — приложение связывает значения и отправляет SQL-запрос на сервер базы данных. Сервер базы данных выполняет запрос с привязанными значениями, используя внутренние ресурсы сервера, выделенные на этапе подготовки.

Создание подготовленного запроса в PDO

Чтобы создать подготовленный запрос в PDO, выполните действия, которые я опишу ниже.

1. Во-первых, создаем шаблонный SQL-запрос. Например:

$sql = 'INSERT INTO authors (first_name, last_name)
        VALUES (?, ?)';

В этом выражении INSERT есть два вопросительных знака (?). Они называются позиционными заполнителями.

При выполнении оператора необходимо передать значения в позиционные заполнители по их позициям. Другими словами, например, в первый заполнитель нужно передать имя, а во второй — фамилию.

2. Во-вторых, вызовите метод prepare() экземпляра PDO:

$statement = $pdo->prepare($sql);

Метод prepare() возвращает новый экземпляр класса PDOStatement.

3. В-третьих, вызовите метод execute() и передайте значения заполнителям:

$statement->execute(['Sandra', 'Aamodt']);

Метод execute() заменит первый заполнитель на ‘Sandra’, а второй — на ‘Aamodt’ в операторе вставки.

Соединим все вместе.

Ниже показано, как использовать подготовленный запрос для вставки новой строки в таблицу «авторов»:

<?php

$pdo = require 'connect.php';

$sql = 'insert into authors(first_name, last_name)
        values(?,?)';

$statement = $pdo->prepare($sql);

$statement->execute(['Sandra', 'Aamodt']);

Выше в коде мы использовали вставку файла с данными для соединения с Базой Данных, как в статье PDO: cоединение с Базой Данных.

Использование именованных заполнителей

Когда вы используете позиционные заполнители в операторе SQL, вам необходимо передать значения, соответствующие позициям заполнителей.

Если в SQL-операторе много заполнителей, очень легко использовать неправильные позиции. Чтобы избежать этого, можно использовать именованные заполнители. Например:

$sql = 'INSERT INTO authors (first_name, last_name)
        VALUES (:first_name,:last_name)';

В этом примере вместо вопросительных знаков (?) используется имя параметра, перед которым ставится двоеточие (:). Двоеточие требуется в операторе SQL.

При выполнении оператора необходимо передать ассоциативный массив в метод execute() следующим образом:

$statement->execute([
	'first_name' => 'Henry',
	'last_name' => 'Aaron'
]);

Обратите внимание, что важен ключ массива, а не порядок элементов. Также, можно использовать символ : в ключах массива по желанию:

$statement->execute([
	':first_name' => 'Henry',
	':last_name' => 'Aaron'
]);

Порядок элементов массива не важен, поэтому вы можете использовать массив с элементами в любом порядке. Например:

$statement->execute([
	'last_name' => 'Aaron',
	'first_name' => 'Henry',
]);

Соединим все вместе.

<?php

$pdo = require 'connect.php';

$sql = 'INSERT INTO authors (first_name, last_name)
        VALUES (:first_name,:last_name)';

$statement = $pdo->prepare($sql);

$statement->execute([
	'last_name' => 'Aaron',
	'first_name' => 'Henry',
]);

Связанные значения

В приведенных выше примерах мы передаем значения в метод execute() для выполнения запроса. Эти утверждения называются не связанными запросами.

Помимо несвязанных запросов, PDO также поддерживает связанные запросы. Связанные запросы позволяют явно связать значение или переменную с именованным или позиционным заполнителем.

Чтобы связать значение, используется метод bindValue() объекта PDOStatement:

public PDOStatement::bindValue ( mixed $parameter , mixed $value , int $data_type = PDO::PARAM_STR ) : bool

Метод bindValue() имеет три параметра:

  • $parameter задает имя параметра :parameter, если в запросе используются именованные заполнители, или индекс параметра, если в запросе используются позиционные заполнители. В случае использования позиционных заполнителей первый параметр начинается с индекса 1.
  • $value указывает значение, которое нужно привязать к запросу.
  • $data_type указывает тип данных для параметра, используя PDO::PARAM_*, например, PDO::PARAM_INT. По умолчанию $data_type — это PDO::PARAM_STR.

В следующем примере показано, как вставить автора Nick Abadzis в таблицу authors с помощью связанного запроса:

<?php

$pdo = require 'connect.php';

$sql = 'INSERT INTO authors (first_name, last_name)
        VALUES (?, ?)';

$statement = $pdo->prepare($sql);

$statement->bindValue(':first_name', 'Nick');
$statement->bindValue(':last_name', 'Abadzis');

$statement->execute();

Когда вы используете метод bindValue(), метод execute() выполняет запрос со значениями, переданными методу bindValue(), а не со значениями на момент выполнения метода execute(). Например:

<?php

$pdo = require 'connect.php';

$sql = 'INSERT INTO authors (first_name, last_name)
        VALUES (:first_name,:last_name)';

$statement = $pdo->prepare($sql);

$author = [
	'first_name' => 'Chris',
	'last_name' => 'Abani',
];

$statement->bindValue(':first_name', $author['first_name']);
$statement->bindValue(':last_name', $author['last_name']);

// изменение автора
$author['first_name'] = 'Tom';
$author['last_name'] = 'Abate';

// выполнение запроса со значением Chris Abani
$statement->execute();

В данном примере:

  1. Во-первых, привязываем значения ‘Chris’ и ‘Abate’ к параметрам имени и фамилии.
  2. Во-вторых, изменяем значения переменной $author.
  3. В-третьих, выполняем запрос. Однако метод execute() использует значения, переданные методу bindValue(), а не значение $author на момент выполнения метода execute().

Поэтому в дело вступает метод bindParam().

Метод bindParam()

Для выполнения запроса, значения параметров которого оцениваются во время выполнения метода execute(), используется метод bindParam():

public PDOStatement::bindParam ( mixed $parameter , mixed &$variable , int $data_type = PDO::PARAM_STR , int $length = ? , mixed $driver_options = ? ) : bool

Следующий пример иллюстрирует использование метода bindParam() для вставки нового автора в таблицу authors:

<?php

$pdo = require 'connect.php';

$sql = 'insert into authors(first_name, last_name)
        values(:first_name,:last_name)';

$statement = $pdo->prepare($sql);

$author = [
	'first_name' => 'Chris',
	'last_name' => 'Abani',
];

$statement->bindParam(':first_name', $author['first_name']);
$statement->bindParam(':last_name', $author['last_name']);

// изменение переменной автора
$author['first_name'] = 'Tom';
$author['last_name'] = 'Abate';

// выполняем запрос со значением Tom Abate
$statement->execute();

В этом примере метод execute() оценивает переменную $author во время выполнения, поэтому вместо нее используются значения ‘Tom’ и ‘Abage’.

Используйте подготовленный запрос PHP для многократного выполнения запроса с разными значениями.

Используйте позиционные заполнители (?) или именованные заполнители (:parameter) в SQL-запросе, прежде чем передать его в метод prepare() объекта PDOStatement.

Используйте метод execute() со значениями для запуска несвязанного запроса.

Используйте метод bindValue() или bindParam() для привязки значений к связанному запросу.

Вставка данных

Как и в предыдущем примере, нам сначала нужно соединение с базой данных, которое выполняется путем создания нового объекта PDO — смотрите выше пример того, как это сделать, если вы не уверены.

Поскольку соединение с базой данных MySQL является объектом PDO, вы должны использовать различные методы PDO (любую функцию, которая является частью любого объекта) для подготовки и выполнения запросов. Методы объектов вызываются так:

$the_Object->the_Method();

PDO позволяет подготовить SQL-код перед его выполнением. SQL-запрос обрабатывается и исправляется перед выполнением.

Упрощенная атака SQL-инъекцией может быть выполнена просто путем ввода SQL-кода в поле на форме. Например:

// хакер пишет это в поле имени пользователя формы входа
john"; DROP DATABASE user_table;

// финальный запрос становится таким
"SELECT * FROM user_table WHERE username = john"; DROP DATABASE user_table;

Так как существует синтаксически корректный SQL-код, точка с запятой делает DROP DATABASE user_table новым SQL-запросом, а ваша пользовательская таблица удаляется.

Подготовленные операторы не позволяют символам « и ; завершить исходный запрос, и вредоносная инструкция DROP DATABASE никогда не будет выполнена.

Важно! Вы всегда должны использовать подготовленные операторы при отправке или получении данных из базы данных с PDO.

Чтобы использовать подготовленные операторы, вы должны написать новую переменную, которая вызывает метод prepare() объекта базы данных.

Переходим к правильному коду:

<?php
$servername = "mysql.hostinger.com";
$database = "u266072517_name"; 
$username = "u266072517_user";
$password = "buystuffpwd";
$sql = "mysql:host=$servername;dbname=$database;";
$dsn_Options = [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION];

// создание нового соединения с базой данных MySQL с помощью PDO, $my_Db_Connection - это объект
try { 
  $my_Db_Connection = new PDO($sql, $username, $password, $dsn_Options);
  echo "Connected successfully";
} catch (PDOException $error) {
  echo 'Connection error: ' . $error->getMessage();
}

// устанавливаем переменные для человека, которого мы хотим добавить в базу данных
$first_Name = "Test";
$last_Name = "Testing";
$email = "Testing@testing.com";

// здесь мы создаем переменную, которая вызывает метод prepare() объекта базы данных.
// SQL-запрос, который вы хотите выполнить, вводится как параметр, а заполнители записываются следующим образом: placeholder_name
$my_Insert_Statement = $my_Db_Connection->prepare("INSERT INTO Students (name, lastname, email) VALUES (:first_name, :last_name, :email)");

// теперь мы сообщаем скрипту, на какую переменную фактически ссылается каждый заполнитель, используя метод bindParam()
// первый параметр - это место в выражении выше - второй параметр - это переменная, к которой он должен относиться
$my_Insert_Statement->bindParam(:first_name, $first_Name);
$my_Insert_Statement->bindParam(:last_name, $last_Name);
$my_Insert_Statement->bindParam(:email, $email);

// выполните запрос, используя данные, которые мы только что определили
// метод execute() возвращает TRUE, если он успешен, и FALSE, если нет, позволяя писать свои собственные сообщения здесь
if ($my_Insert_Statement->execute()) {
  echo "New record created successfully";
} else {
  echo "Unable to create record";
}

// на этом этапе вы можете изменить данные переменных и повторить процедуру для добавления новых данных в базу данных
$first_Name = "John";
$last_Name = "Smith";
$email = "john.smith@email.com";
$my_Insert_Statement->execute();

// выполняем снова, когда переменные изменились
if ($my_Insert_Statement->execute()) {
  echo "New record created successfully";
} else {
  echo "Unable to create record";
}

В строках 28, 29 и 30 мы используем метод bindParam() объекта базы данных. Также существует совершенно другой метод bindValue().

bindParam() — Этот метод оценивает данные при достижении метода execute(). В первый раз, когда скрипт достигает метода execute(), он видит, что $first_Name соответствует "Test", связывает это значение и выполняет запрос.

Когда сценарий достигает второго метода execute(), он видит, что $first_Name теперь соответствует "John", связывает это значение и снова запускает запрос с новыми значениями. Важно помнить, что мы определили запрос один раз и повторно использовали его с разными данными в разных точках скрипта.

bindValue() — Этот метод оценивает данные, как только достигается bindValue(). Поскольку значение $first_Name было установлено на "Test" при достижении bindValue(), оно будет использоваться каждый раз, когда вызывается метод execute() для $my_Insert_Statement.

Обратите внимание, что мы повторно используем переменную $first_Name и второй раз даем ей новое значение. Если вы проверите свою базу данных после выполнения этого скрипта, у вас есть оба определенных имени, несмотря на то, что в конце скрипта переменная $first_Name равна "John". Помните, что PHP оценивает весь скрипт перед его фактическим выполнением.

Если вы обновите скрипт, чтобы заменить bindParam на bindValue, вы дважды вставите в MySQL "Test Testing" в БД и "John Smith" будет проигнорирован.

SELECT в PDO без параметров

Существует несколько способов выполнения SELECT-запроса с помощью PDO, которые различаются в основном наличием параметров, типом параметров и типом результата. Я покажу примеры для каждого случая, чтобы вы могли выбрать тот, который подходит вам больше всего.

Просто убедитесь, что у вас правильно настроена переменная соединения PDO, которая должна выполнять SQL-запросы с помощью PDO и сообщать вам о возможных ошибках.

Если в запросе не будут использоваться переменные, мы можем использовать обычный метод query() вместо prepare и execute.

// получение всех пользователей
$stmt = $pdo->query("SELECT * FROM users");

Это даст нам объект $stmt, который может быть использован для получения актуальных строк.

Получение одной строки

Если запрос должен вернуть только одну строку, то можно просто вызвать метод fetch() переменной $stmt:

// получение последнего зарегистрированного пользователя
$stmt = $pdo->query("SELECT * FROM users ORDER BY id DESC LIMIT 1");
$user = $stmt->fetch();

Обратите внимание, что в PHP вы можете «цепочкой» вызывать методы, вызывая метод уже возвращенного объекта, например:

$user = $pdo->query("SELECT * FROM users ORDER BY id DESC LIMIT 1")->fetch();

Выбор нескольких строк

Существует два способа получения нескольких строк, возвращенных в результате запроса. Самый традиционный способ — использовать метод fetch() в цикле while:

$stmt = $pdo->query("SELECT * FROM users");
while ($row = $stmt->fetch()) {
    echo $row['name']."<br />\n";
}

Этот метод может быть рекомендован, если строки должны обрабатываться по одной. Например, если такая обработка является единственным действием, которое необходимо выполнить, или если данные должны быть как-то предварительно обработаны перед использованием.

Но наиболее предпочтительным способом получения нескольких строк, которые должны быть показаны на странице, является вызов замечательного вспомогательного метода fetchAll(). Он поместит все строки, возвращенные после запроса, в массив PHP, который позже можно будет использовать для вывода данных с помощью шаблона (что считается эффективнее, чем вывод данных прямо во время процесса fetch). Таким образом, код будет выглядеть следующим образом:

$data = $pdo->query("SELECT * FROM users")->fetchAll();
// где-то позднее:
foreach ($data as $row) {
    echo $row['name']."<br />\n";
}

SELECT в PDO с параметрами

Но чаще всего нам приходится использовать переменную или две в запросе, и в таком случае мы должны использовать подготовленный запрос (также называемый запросом с параметрами), сначала подготавливая запрос с параметрами (или плейсхолдерами), а затем выполняя его, передавая переменные отдельно.

В PDO мы можем использовать как позиционные, так и именованные плейсхолдеры. Для простых запросов лично я предпочитаю позиционные заполнители, мне они кажутся менее громоздкими, но это дело вкуса.

Запрос SELECT с позиционными заполнителями

// выбрать конкретного пользователя по id
$stmt = $pdo->prepare("SELECT * FROM users WHERE id=?");
$stmt->execute([$id]); 
$user = $stmt->fetch();

Запрос SELECT с именованными заполнителями

// выбрать конкретного пользователя по id
$stmt = $pdo->prepare("SELECT * FROM users WHERE id=:id");
$stmt->execute(['id' => $id]); 
$user = $stmt->fetch();

Выбор нескольких строк

Получение нескольких строк с помощью подготовленного запроса будет идентично показанному выше запросу:

$stmt = $pdo->prepare("SELECT * FROM users LIMIT ?, ?");
$stmt->execute([$limit, $offset]); 
while ($row = $stmt->fetch()) {
    echo $row['name']."<br />\n";
}

Или:

$stmt = $pdo->prepare("SELECT * FROM users LIMIT :limit, :offset");
$stmt->execute(['limit' => $limit, 'offset' => $offset]); 
$data = $stmt->fetchAll();
// где-то позднее:
foreach ($data as $row) {
    echo $row['name']."<br />\n";
}

Обработка ошибок

PDO поддерживает три различные стратегии обработки ошибок:

  • PDO::ERROR_SILENT — PDO устанавливает код ошибки для проверки с помощью методов PDO::errorCode() и PDO::errorInfo(). PDO::ERROR_SILENT — это режим по умолчанию.
  • PDO::ERRMODE_WARNING — помимо установки кода ошибки, PDO выдает сообщение E_WARNING.
  • PDO::ERRMODE_EXCEPTION — Помимо установки кода ошибки, PDO вызовет исключение PDOException.

Чтобы задать стратегию обработки ошибок, вы можете передать ассоциативный массив в конструктор PDO следующим образом:

$pdo = new PDO($dsn, $user, $password, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);

Или вы можете использовать метод setAttribute() экземпляра PDO:

$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

Решение проблем

Существует несколько распространенных проблем при подключении к базе данных MySQL.

Если драйвер MySQL не включен в файл php.ini, вы получите сообщение об ошибке:

could not find driver

Если вы указали неправильный пароль, вы получите следующее сообщение об ошибке:

SQLSTATE[HY000] [1045] Access denied for user 'root'@'localhost' (using password: YES)

Если вы указали неверное имя базы данных или база данных не существует, вы получите следующее сообщение об ошибке:

SQLSTATE[HY000] [1049] Unknown database 'bookdb'

Если вы укажете неверное имя хоста базы данных, появится следующее сообщение об ошибке:

SQLSTATE[HY000] [2002] php_network_getaddresses: getaddrinfo failed: No such host is known.

Если запрос, который мы выполнили и вставили в базу данных MySQL, был успешным, мы увидим следующее сообщение вроде:

Connect Successfully
New record created successfully

Однако бывают случаи, когда вставка новой записи будет с ошибкой при SQL вставке. Но не стоит беспокоиться, есть несколько способов исправить эти ошибки MySQL.

В строке 7 PDO-соединения настраивается режим «Ошибка» для отображения всех исключений (display all exceptions). Если бы это было отключено в скрипте и запрос бы не удался, то вы бы не получили никаких сообщений об ошибках. При включенном режиме исключений отображается конкретная проблема.

Важно! Это следует использовать только при разработке скрипта, так как он может раскрыть имена баз данных и таблиц, которые вы, возможно, предпочтете скрывать от любого, кто может пытаться получить злонамеренный доступ к вашим данным.

В приведенном выше случае, когда вместо круглых скобок были использованы фигурные скобки, ошибка выглядит аналогично:

Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; 
check the manual that corresponds to your MySQL server version for the right syntax to use near '{name, lastname, email} VALUES ('Thom', 'Vial', 'thom.v@some.com')' at line 1"

Другие возможные проблемы, с которыми вы можете столкнуться:

  • Указаны неверные колонки (несуществующие колонки или орфографическая ошибка).
  • Один тип значения присваивается другому типу столбца. Например, если мы попытаемся присвоить число 47 в столбце Name, мы получим ошибку, потому что это должно быть строковое значение. Но если бы мы назначили число в кавычках, например, «47», это сработало бы, потому что наше число будет назначено столбцу в виде строки.
  • Попытка ввести данные в таблицу, которой не существует, или орфографическая ошибка таблицы.

Все эти ошибки можно легко исправить, следуя рекомендациям по сообщениям об ошибках или проверяя журнал ошибок.

После успешного ввода данных мы должны увидеть, что они добавлены в нашу базу данных. Вот пример таблицы, в которую мы добавили наши данные при просмотре из phpMyAdmin.

Теперь вы знаете как использовать PHP для вставки данных в базу данных MySQL с помощью MySQLi и PDO.

Вы также узнали, как устранять распространенные ошибки подключения. Знание того, как использовать PHP для добавления данных в базу данных MySQL, полезно независимо от того, учитесь ли вы программировать или создаете свой веб-сайт.

Опубликовано 5 февраля 2023 в 12:00
Обновлено 9 января 2024 в 14:11
Категория: Блог
Теги: