Avatar ·

Почему нельзя использовать устаревшие функции mysql_* в PHP и чем их заменить?

Всем привет! Я начинающий PHP-разработчик, учусь по старым учебникам и видео на YouTube. Во всех примерах подключение к базе данных MySQL делается через функции mysql_connect(), mysql_query() и т.д. У меня всё работает, но я заметил, что в современных туториалах эти функции не используют. Более того, PhpStorm подчёркивает их красным и пишет "Deprecated". Вот как я сейчас пишу код: ```php $link = mysql_connect('localhost', 'root', ''); mysql_select_db('myblog', $link); $result = mysql_query("SELECT * FROM users WHERE id = " . $_GET['id']); while ($row = mysql_fetch_assoc($result)) { echo $row['name']; } ``` Всё вроде работает, но я слышал, что это опасно. Можете объяснить простыми словами: почему mysql_* — это зло? И что вместо них использовать? Мне нужны не просто слова "они устарели", а конкретные причины. И ещё — как правильно переписать мой код, чтобы он был современным и безопасным? Заранее спасибо за развёрнутый ответ! <<>>

Почему mysql_* — это мёртвая технология?

Вы столкнулись с классической проблемой начинающих: старые учебники и привычка. Функции mysql_* были удалены из PHP начиная с версии 7.0. Это значит, что ваш код просто не будет работать на современных серверах. Но главное — не это, а три фундаментальные проблемы:

  • SQL-инъекции — ваш код в вопросе содержит критическую уязвимость. Переменная $_GET['id'] напрямую вставляется в запрос. Злоумышленник может передать ?id=1; DROP TABLE users — и вы потеряете данные.
  • Отсутствие подготовленных выражений — mysql_* не поддерживают параметризованные запросы. Приходится вручную экранировать данные через mysql_real_escape_string(), но это не панацея (проблемы с кодировками, пропуски).
  • Смешивание кода и данных — вы пишете запрос как строку с конкатенацией. Это делает код нечитаемым и небезопасным.

Современное решение: PDO (PHP Data Objects)

PDO — это расширение для работы с базами данных, которое поддерживает подготовленные выражения и работает с MySQL, PostgreSQL, SQLite и другими СУБД. Вот как переписать ваш код:

<?php
// 1. Подключение с обработкой ошибок
$dsn = 'mysql:host=localhost;dbname=myblog;charset=utf8mb4';
$user = 'root';
$password = '';

try {
    $pdo = new PDO($dsn, $user, $password);
    // Включаем режим исключений для ошибок
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    die('Ошибка подключения: ' . $e->getMessage());
}

// 2. Подготовленный запрос (безопасно!)
$id = $_GET['id'] ?? 0; // защита от неопределённого ключа
$stmt = $pdo->prepare("SELECT name FROM users WHERE id = :id");
$stmt->execute([':id' => $id]);

// 3. Получение результатов
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
    echo htmlspecialchars($row['name']); // защита от XSS
}
?>

Почему это лучше?

  • Безопасность: PDO сам экранирует данные. Даже если передать 1; DROP TABLE — это будет воспринято как строка, а не как часть SQL.
  • Читаемость: запрос отделён от данных. Места для ошибок меньше.
  • Переносимость: достаточно сменить строку подключения DSN — и код работает с другой БД.
  • Обработка ошибок: через исключения вы всегда знаете, что пошло не так.

Альтернатива: MySQLi (MySQL improved)

Если вы не хотите переходить на PDO, используйте MySQLi — он тоже поддерживает подготовленные выражения. Но PDO предпочтительнее из-за универсальности.

Итог: забудьте про mysql_* как страшный сон. Учите PDO — это стандарт индустрии. И всегда используйте подготовленные выражения, даже если кажется, что "этот запрос безопасен".

<<>>

Дополнение: почему не стоит даже начинать с mysql_*

Коллега выше отлично объяснил техническую сторону. Я добавлю важный психологический момент: используя устаревшие функции, вы формируете вредные привычки. Когда вы перейдёте на PDO или MySQLi, вам придётся переучиваться. А это больно и долго.

Ещё один аргумент — сообщество. Если вы выложите код с mysql_* на GitHub или в вопрос на Stack Overflow, вас просто заминусуют. Никто не захочет помогать человеку, который игнорирует современные стандарты.

И последнее: производительность. PDO использует кэширование планов запросов при повторных вызовах подготовленных выражений. Ваш старый код с mysql_query каждый раз парсит запрос заново — это медленнее.

Совет: установите PHP 8.x и включите строгий режим ошибок. Тогда все mysql_* сразу вызовут фатальные ошибки — это лучшая мотивация для перехода на PDO. Удачи в изучении!