> Почему перешли с расширения mysql на PDO в PHP (PHP)
Уровень: senior · Роль: backend · Язык: PHP · Категория: Технические вопросы
Компании: vanta
Стек: PHP
> Пример ответа
Короткий ответ
Переход с расширения mysql на PDO обусловлен тремя ключевыми причинами: безопасность, совместимость и архитектура. Расширение mysql было deprecated в PHP 5.5 и удалено в PHP 7.0, так как не поддерживало prepared statements, что вело к SQL-инъекциям. PDO предоставляет единый API для разных СУБД, поддерживает prepared statements, транзакции и объектно-ориентированный интерфейс. Это стандарт де-факто для работы с БД в современном PHP.
Подробное объяснение
Расширение mysql (не путать с mysqli) было разработано для PHP 3 и 4, когда требования к безопасности и гибкости были ниже. Оно имело процедурный API, не поддерживало prepared statements, транзакции на уровне API, и было привязано только к MySQL. Основные проблемы:
- SQL-инъекции: данные приходилось экранировать вручную через
mysql_real_escape_string, что легко забыть или сделать неправильно. - Отсутствие абстракции: код был жёстко завязан на MySQL, миграция на PostgreSQL или SQLite требовала полной переработки.
- Устаревшая архитектура: процедурные функции, глобальное состояние соединения, отсутствие исключений - ошибки обрабатывались через возвращаемые значения и
mysql_error(). - Отсутствие поддержки новых возможностей: например,
mysqlnd(native driver) появился только вmysqliи PDO.
PDO (PHP Data Objects) решает эти проблемы:
- Prepared statements: параметризованные запросы отделяют SQL от данных, что исключает инъекции при правильном использовании.
- Абстракция БД: единый интерфейс для MySQL, PostgreSQL, SQLite, Oracle и других. Достаточно сменить DSN и драйвер.
- Объектный API: интуитивно понятный, с цепочками вызовов и исключениями.
- Транзакции: встроенные методы
beginTransaction(),commit(),rollBack(). - Гибкость fetch-режимов: можно получать результаты как ассоциативные массивы, объекты, в виде колонки и т.д.
Важно отметить trade-off: PDO не поддерживает некоторые специфичные для MySQL функции (например, LOAD DATA LOCAL INFILE через prepared statements), но для большинства приложений это не критично. Также PDO использует эмуляцию prepared statements по умолчанию, что может снижать производительность на некоторых драйверах - это настраивается через PDO::ATTR_EMULATE_PREPARES.
На практике
В реальном проекте переход означает:
- Замена
mysql_connect()наnew PDO($dsn, $user, $pass). - Замена ручного экранирования на prepared statements с плейсхолдерами
?или именованными:name. - Обработка ошибок через
try/catchвместо проверкиif (!$result). - Использование
fetchAll(),fetch()вместо цикловwhile ($row = mysql_fetch_assoc()). - Настройка атрибутов:
ERRMODE_EXCEPTION,DEFAULT_FETCH_MODE,ATTR_EMULATE_PREPARES.
Также важно учитывать, что PDO - это не ORM, а низкоуровневый доступ к БД. Для сложных проектов поверх PDO строят Query Builder или ORM (Doctrine, Eloquent), но PDO остаётся базовым слоем.
Пример кода
PHP// Старый подход (mysql)$conn = mysql_connect('localhost', 'user', 'pass');mysql_select_db('app', $conn);$id = $_GET['id'];$result = mysql_query("SELECT * FROM users WHERE id = " . mysql_real_escape_string($id), $conn);while ($row = mysql_fetch_assoc($result)) {echo $row['name'];}// Новый подход (PDO)$dsn = 'mysql:host=localhost;dbname=app;charset=utf8mb4';$pdo = new PDO($dsn, 'user', 'pass', [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,PDO::ATTR_EMULATE_PREPARES => false,]);$stmt = $pdo->prepare('SELECT * FROM users WHERE id = :id');$stmt->execute(['id' => $_GET['id']]);foreach ($stmt as $row) {echo $row['name'];}
Как отвечать на собеседовании
Начните с краткого ответа: deprecated, безопасность, абстракция. Затем перечислите конкретные недостатки mysql: отсутствие prepared statements, процедурный API, привязка к MySQL. Подчеркните, что PDO - это не просто замена, а смена парадигмы: параметризация, исключения, единый интерфейс. Упомяните, что mysqli тоже поддерживает prepared statements, но PDO выигрывает за счёт абстракции. Если спросят про производительность, скажите, что разница минимальна, а безопасность важнее. Завершите примером кода, показывающим разницу в обработке ошибок и запросов.
Что проверяет интервьюер
- Понимание причин deprecated и истории развития PHP.
- Знание разницы между
mysql,mysqliи PDO. - Практическое владение prepared statements и обработкой ошибок.
- Понимание trade-off между абстракцией и специфичностью СУБД.
- Способность объяснить архитектурные решения простыми словами.
Типичные ошибки
- Путать
mysqlиmysqli- это разные расширения,mysqliдо сих пор поддерживается. - Говорить, что PDO "быстрее" - это не всегда так, главное преимущество в безопасности и абстракции.
- Не упоминать про
ATTR_EMULATE_PREPARES- это важный нюанс для реальной безопасности. - Сводить ответ только к SQL-инъекциям, забывая про миграцию между СУБД.
- Приводить пример без обработки исключений - это показывает недостаточный уровень практики.
> Похожие задачи по PHP
Какие минусы наследования
Какой паттерн реализует Doctrine ORM
Какой порядок параметров у функции array_filter в PHP
Что произойдет при вызове асинхронной функции без await?
> Похожие задачи по backend
Какие минусы наследования
Какой паттерн реализует Doctrine ORM
Какой порядок параметров у функции array_filter в PHP
Что произойдет при вызове асинхронной функции без await?
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью