PHP и MySQL через PDO: первая база без SQL-инъекций

PHP часто используют вместе с MySQL: формы, заявки, каталоги, WordPress, админки, личные кабинеты. Но начинать нужно не со старых mysql_* функций и не со склейки SQL-строк. В этом уроке подключимся к MySQL через PDO, прочитаем список задач и добавим новую запись через prepared statement

Главная цель: увидеть безопасный базовый путь PDO -> prepare -> execute, а не копировать уязвимый код из старых примеров

Что получится в конце

У нас будет таблица tasks:

create table tasks (
    id int auto_increment primary key,
    title varchar(255) not null,
    done tinyint(1) not null default 0
);

PHP-страница покажет список задач и позволит добавить новую через POST-форму

Подготовка базы

Создайте базу php_lessons и таблицу:

create database php_lessons character set utf8mb4 collate utf8mb4_unicode_ci;
use php_lessons;

create table tasks (
    id int auto_increment primary key,
    title varchar(255) not null,
    done tinyint(1) not null default 0
);

insert into tasks (title) values ('Разобрать PDO в PHP');

Пользователь, пароль и хост зависят от вашей локальной среды: XAMPP, Open Server, Docker или отдельный MySQL

Подключение через PDO

Создайте index.php:

<?php
$pdo = new PDO(
    'mysql:host=127.0.0.1;dbname=php_lessons;charset=utf8mb4',
    'root',
    '',
    [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    ]
);

ERRMODE_EXCEPTION нужен, чтобы ошибки базы не превращались в молчание. FETCH_ASSOC делает строки удобными ассоциативными массивами

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

Читаем задачи

Добавьте:

$statement = $pdo->query('select id, title, done from tasks order by id desc');
$tasks = $statement->fetchAll();

Теперь выведите список:

<!doctype html>
<html lang="ru">
<head>
    <meta charset="utf-8">
    <title>PHP и MySQL</title>
</head>
<body>
    <h1>Задачи</h1>
    <ul>
        <?php foreach ($tasks as $task): ?>
            <li>
                <?= htmlspecialchars($task['title']) ?>
                <?= $task['done'] ? 'готово' : 'в работе' ?>
            </li>
        <?php endforeach; ?>
    </ul>
</body>
</html>

Если список появился, SELECT работает

Добавляем форму

Перед списком:

<form method="post">
    <input name="title" placeholder="Новая задача">
    <button type="submit">Добавить</button>
</form>

В начало файла после подключения добавьте обработку POST:

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $title = trim($_POST['title'] ?? '');

    if ($title !== '') {
        $statement = $pdo->prepare('insert into tasks (title) values (:title)');
        $statement->execute([
            'title' => $title,
        ]);

        header('Location: /');
        exit;
    }
}

header('Location: /') после успешного добавления защищает от повторной отправки формы при обновлении страницы

Почему prepare лучше склейки SQL

Плохой путь:

$sql = "insert into tasks (title) values ('$title')";
$pdo->exec($sql);

Если пользователь отправит кавычки или SQL-фрагмент, запрос может сломаться или стать уязвимым

Правильный путь:

$statement = $pdo->prepare('insert into tasks (title) values (:title)');
$statement->execute(['title' => $title]);

SQL и данные передаются отдельно. Это базовая защита от SQL-инъекций

Частые ошибки

could not find driver. Не включено расширение PDO MySQL. Проверьте phpinfo() и настройки вашей сборки PHP

Access denied for user. Неверный пользователь, пароль или права в MySQL

Unknown database. База не создана или имя в DSN написано иначе

Headers already sent. header() вызван после вывода HTML. Обработка POST и redirect должны быть до вывода страницы

Что может быть еще интересно по этой теме

PDO заменяет MySQL? Нет. PDO — интерфейс PHP для работы с базой. MySQL остается сервером базы данных

Prepared statements нужны только для INSERT? Нет. Они нужны для любых запросов с пользовательскими данными: SELECT, UPDATE, DELETE

htmlspecialchars защищает базу? Нет. Он нужен для HTML-вывода. Для SQL используйте prepared statements

Стоит ли начинать с ORM? Новичку полезно сначала понять PDO и SQL. ORM можно добавить позже, когда база уже не выглядит магией

Что открыть дальше

Оцените статью
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x