PHP MySQL SELECT через PDO: как получить и вывести данные
PHP получает записи MySQL через SELECT и объект PDO. Используйте prepare() и execute() для внешних значений. Перед выводом применяйте htmlspecialchars(). Так запрос защищает SQL, а вывод защищает HTML.
Что подготовить для запроса PHP к MySQL
Пример читает таблицу employees. В ней есть столбцы lastname, firstname и jobtitle.
PHP подключается к MySQL через драйвер pdo_mysql. Создайте рядом с будущей страницей файл dbconfig.php и запишите в него реквизиты базы.
<?php
$host = '127.0.0.1';
$dbname = 'company';
$username = 'app_reader';
$password = 'replace_with_your_password';Замените 4 значения своими реквизитами. Имя company приведено для примера.
Файл с реквизитами базу не создает. Пароль храните вне публичного каталога.
Учетной записи для чтения хватит права SELECT. Администратора к обычной странице не подключайте.
Строка подключения задает сервер, базу и кодировку. Режим ERRMODE_EXCEPTION передает ошибки в исключения.
Режим FETCH_ASSOC возвращает столбцы по именам. Настройте его сразу при создании объекта PDO.
$pdo = new PDO(
"mysql:host=$host;dbname=$dbname;charset=utf8mb4",
$username,
$password,
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
]
);Как выполнить SELECT и вывести таблицу
Подготовленный запрос отделяет SQL от значения поиска. Полный файл соединяет базу, получает записи и выводит HTML-таблицу.
<?php
require __DIR__ . '/dbconfig.php';
try {
$pdo = new PDO(
"mysql:host=$host;dbname=$dbname;charset=utf8mb4",
$username,
$password,
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
]
);
$sql = 'SELECT lastname, firstname, jobtitle
FROM employees
WHERE lastname LIKE ?
ORDER BY lastname';
$q = $pdo->prepare($sql);
$q->execute(['%']);
} catch (PDOException $e) {
error_log($e->getMessage());
http_response_code(500);
exit('Не удалось получить список сотрудников.');
}
function escapeHtml($value): string
{
return htmlspecialchars(
(string) $value,
ENT_QUOTES | ENT_SUBSTITUTE,
'UTF-8'
);
}
?>
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Сотрудники</title>
</head>
<body>
<h2>Сотрудники</h2>
<table>
<thead>
<tr>
<th>Фамилия</th>
<th>Имя</th>
<th>Должность</th>
</tr>
</thead>
<tbody>
<?php $hasRows = false; ?>
<?php while (($row = $q->fetch()) !== false): ?>
<?php $hasRows = true; ?>
<tr>
<td><?= escapeHtml($row['lastname']) ?></td>
<td><?= escapeHtml($row['firstname']) ?></td>
<td><?= escapeHtml($row['jobtitle']) ?></td>
</tr>
<?php endwhile; ?>
<?php if (!$hasRows): ?>
<tr>
<td colspan="3">Сотрудники не найдены.</td>
</tr>
<?php endif; ?>
</tbody>
</table>
</body>
</html>Сохраните код в файле employees.php. Положите его рядом с dbconfig.php.
Откройте терминал в этой папке. Запустите php -S localhost:8000.
В браузере откройте http://localhost:8000/employees.php. Страница покажет таблицу сотрудников.
Пустая выборка выведет сообщение «Сотрудники не найдены». Ошибка соединения вернет общий текст, а подробности попадут в журнал.

Метод fetch() возвращает одну строку. После последней строки он возвращает false.
Функция escapeHtml() экранирует каждую ячейку перед выводом. Она принимает и строки, и числовые значения.
Как добавить поиск по фамилии
Полный файл выполняет execute(['%']) и показывает все фамилии. Для поиска замените блок запроса внутри try.
Позиционный заполнитель для параметра suffix
Получите параметр из адресной строки. Проверка типа не дает массиву попасть в шаблон поиска.
$suffix = $_GET['suffix'] ?? '';
if (!is_string($suffix)) {
http_response_code(400);
exit('Параметр suffix должен быть строкой.');
}
$sql = 'SELECT lastname, firstname, jobtitle
FROM employees
WHERE lastname LIKE ?
ORDER BY lastname';
$q = $pdo->prepare($sql);
$q->execute(['%' . $suffix]);Замените исходный блок внутри try этим кодом. HTML-часть с таблицей менять не нужно.
Откройте адрес http://localhost:8000/employees.php?suffix=son. Таблица покажет фамилии, которые заканчиваются на son.
Знак вопроса задает позиционный заполнитель.
PDO передает значение отдельно от SQL. Пользовательский текст не меняет структуру запроса.
Именованные заполнители для двух условий
Имена параметров помогают не перепутать значения в длинном условии. Каждый заполнитель связывается с ключом массива.
$sql = 'SELECT lastname, firstname, jobtitle
FROM employees
WHERE lastname LIKE :lname
OR firstname LIKE :fname';
$q = $pdo->prepare($sql);
$q->execute([
'lname' => '%son',
'fname' => 'Le%',
]);:lname ищет окончание фамилии. :fname ищет начало имени.
Именованные параметры удобны при двух и более условиях.
Типичные ошибки и ограничения SELECT через PDO
Защита SQL и защита HTML решают разные задачи. Подготовленный запрос защищает структуру SQL.
htmlspecialchars() экранирует текст перед вставкой в HTML.
- Склейка SQL. Не вставляйте
$_GETв строку запроса. Передавайте значение через заполнитель. - Кавычки вокруг заполнителя. Запись
LIKE '?'превращает параметр в обычный текст. ИспользуйтеLIKE ?. - Имя столбца в параметре. Заполнитель принимает значение. Он не заменяет имя таблицы или оператора.
- Символы LIKE. Знаки
%и_сохраняют значение шаблонов. Для буквального поиска экранируйте их отдельно. - Неэкранированный вывод. Данные базы могут содержать HTML. Применяйте
htmlspecialchars()к каждой текстовой ячейке. - Подробная ошибка на странице. Не показывайте посетителю
getMessage(). Записывайте детали в журнал.
htmlspecialchars() подходит для текста и атрибутов в кавычках. Она не проверяет URL.
Не вставляйте ее результат в JavaScript или обработчик события.
Метод query() подходит для полностью фиксированного SQL. В нем не должно быть внешних значений.
Для поиска используйте prepare() и execute().
Пустой результат не означает ошибку. Метод fetch() вернет false.
Не используйте rowCount() как универсальный счетчик строк SELECT.
Ошибка could not find driver указывает на отсутствие драйвера PDO. Сообщение Access denied связано с реквизитами или правами.
Ошибка неизвестной таблицы указывает на имя базы или таблицы.
Какой способ выполнения запроса выбрать
Выбор зависит от внешних значений. Фиксированный SQL выполняйте через query().
Поиск пользователя выполняйте через подготовленное выражение.
| Способ | Когда использовать | Как передать значение | Ограничение |
|---|---|---|---|
query() | Фиксированный SELECT без внешних данных | Значений нет | Пользовательский ввод добавлять нельзя |
| Позиционные заполнители | Один или несколько параметров по порядку | execute([$value]) | Порядок массива совпадает со знаками вопроса |
| Именованные заполнители | Несколько условий с разным смыслом | execute(['name' => $value]) | Имена ключей совпадают с запросом |
Берите query() только для SQL без внешнего ввода. Для одного условия подойдет знак вопроса.
Для нескольких условий используйте понятные имена. Так проще сопоставить параметры с условиями запроса.
Популярное за неделю
- Как создать сайт самому в 2026: 4 способа + пошаговая инструкция 34 мин чтения
- Лучшие конструкторы для создания сайтов — плюсы, минусы и сравнения 22 мин чтения
- Как сделать редирект на PHP 6 мин чтения
- Основы ООП в PHP: принципы и примеры 6 мин чтения
- Адаптивный помесячный календарь на AJAX и PHP 2 мин чтения
- Как создать формы регистрации и авторизации на PHP 5 мин чтения
Комментарии