Avatar ·

Ошибка "expects parameter 1 to be resource" в mysql_fetch_array() и других функциях

Всем привет! Я только начал изучать PHP и MySQL, и у меня возникла проблема, которая ставит меня в тупик. Я пытаюсь получить данные из базы данных, но постоянно получаю ошибку: Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given Вот мой код:
<?php
$connection = mysql_connect("localhost", "root", "");
mysql_select_db("test_db");

$query = "SELECT * FROM users WHERE id = " . $_GET['id'];
$result = mysql_query($query);

while ($row = mysql_fetch_array($result)) {
    echo $row['name'] . "<br>";
}
?>
Я проверил, что соединение с базой данных устанавливается, но всё равно получаю эту ошибку. Что я делаю не так? Как правильно получить данные из MySQL? Я слышал, что нужно использовать какие-то проверки, но не понимаю, какие именно. Буду благодарен за подробное объяснение! <<>>

Основная причина ошибки и её решение

Ошибка "expects parameter 1 to be resource, boolean given" возникает, когда функция mysql_fetch_array() (или mysql_fetch_assoc(), mysql_fetch_row() и т.д.) получает не ресурс результата запроса, а значение false. Это происходит, когда запрос mysql_query() завершается неудачей — например, из-за синтаксической ошибки SQL или проблем с базой данных.

В вашем случае проблема усугубляется тем, что вы напрямую подставляете значение из $_GET['id'] в запрос, что делает код уязвимым для SQL-инъекций. Но давайте сначала разберёмся с базовой ошибкой.

Правильный подход: проверка результата запроса

Всегда проверяйте результат выполнения mysql_query() перед тем, как его использовать. Вот исправленная версия вашего кода:

<?php
$connection = mysql_connect("localhost", "root", "");
if (!$connection) {
    die("Ошибка подключения: " . mysql_error());
}

mysql_select_db("test_db");

// ВАЖНО: экранируем входные данные!
$id = mysql_real_escape_string($_GET['id']);
$query = "SELECT * FROM users WHERE id = " . $id;
$result = mysql_query($query);

if (!$result) {
    die("Ошибка запроса: " . mysql_error() . "<br>Запрос: " . $query);
}

while ($row = mysql_fetch_array($result)) {
    echo htmlspecialchars($row['name']) . "<br>";
}

mysql_close($connection);
?>

Ключевые моменты:

  • Проверка подключения: if (!$connection) — убедитесь, что соединение установлено.
  • Проверка результата запроса: if (!$result) — если запрос не удался, вы получите false. Используйте mysql_error() для получения текста ошибки.
  • Экранирование входных данных: mysql_real_escape_string() защищает от SQL-инъекций. Никогда не подставляйте данные напрямую в запрос!
  • Безопасный вывод: htmlspecialchars() предотвращает XSS-атаки при выводе данных на страницу.

Почему возникает false?

Наиболее частые причины, по которым mysql_query() возвращает false:

  • Синтаксическая ошибка в SQL (например, пропущена кавычка или опечатка в имени таблицы).
  • Таблица или база данных не существует.
  • Недостаточно прав доступа для выполнения запроса.
  • Проблемы с соединением (соединение было закрыто или прервано).

Важное замечание

Расширение mysql_* является устаревшим начиная с PHP 5.5.0 и полностью удалено в PHP 7.0.0. Настоятельно рекомендую перейти на MySQLi или PDO. Вот пример с MySQLi:

<?php
$connection = new mysqli("localhost", "root", "", "test_db");
if ($connection->connect_error) {
    die("Ошибка подключения: " . $connection->connect_error);
}

$id = $connection->real_escape_string($_GET['id']);
$query = "SELECT * FROM users WHERE id = " . $id;
$result = $connection->query($query);

if (!$result) {
    die("Ошибка запроса: " . $connection->error);
}

while ($row = $result->fetch_array()) {
    echo htmlspecialchars($row['name']) . "<br>";
}

$connection->close();
?>

Этот подход более современный, безопасный и поддерживается в актуальных версиях PHP.

<<>>

Использование PDO для более безопасной работы

Если вы хотите полностью избежать проблем с экранированием и сделать код более гибким, рекомендую использовать PDO (PHP Data Objects). PDO поддерживает подготовленные запросы, которые автоматически защищают от SQL-инъекций.

<?php
try {
    $pdo = new PDO("mysql:host=localhost;dbname=test_db", "root", "");
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");
    $stmt->execute(['id' => $_GET['id']]);

    while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
        echo htmlspecialchars($row['name']) . "<br>";
    }
} catch (PDOException $e) {
    die("Ошибка: " . $e->getMessage());
}
?>

Преимущества PDO:

  • Подготовленные запросы — автоматическое экранирование данных.
  • Единый интерфейс для разных СУБД (MySQL, PostgreSQL, SQLite и др.).
  • Режим исключений — ошибки обрабатываются через try-catch, что упрощает отладку.
  • Гибкость — поддержка именованных параметров (:id) вместо позиционных (?).

Переход на PDO решит не только текущую проблему, но и сделает ваш код более профессиональным и безопасным в долгосрочной перспективе.