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. Страница покажет таблицу сотрудников.

Пустая выборка выведет сообщение «Сотрудники не найдены». Ошибка соединения вернет общий текст, а подробности попадут в журнал.

Выборка данных сотрудников из MySQL через PHP PDO

Метод 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 без внешнего ввода. Для одного условия подойдет знак вопроса.

Для нескольких условий используйте понятные имена. Так проще сопоставить параметры с условиями запроса.

Комментарии

Оставьте свой комментарий
Пока никто не оставил комментариев