Ошибка mysql_fetch_array(): параметр 1 должен быть resource — решение

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение: та самая ошибка, от которой чешутся руки закрыть браузер

Если вы когда-нибудь писали на PHP запрос к MySQL и вдруг видели в браузере что-то вроде:

Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in /var/www/site/index.php on line 15

...то вы знаете это чувство. Вроде бы всё правильно: подключились, запрос написали, а PHP орёт на вас красным. Особенно обидно, когда код работает на локальном сервере, но на хостинге — нет. Или наоборот.

Эта ошибка — одна из самых популярных на Stack Overflow. Тысячи разработчиков (и мы в их числе) бились головой о клавиатуру, пытаясь понять: «Почему параметр 1 ожидает resource, а получает boolean?»

В этой статье мы не просто разберём причину, а пройдём полный путь: от воспроизведения ошибки до её исправления. А заодно посмотрим, почему старые функции mysql_* давно пора заменить на современные PDO или MySQLi. Поехали!

Как выглядит проблема на практике

Давайте смоделируем ситуацию. У вас есть таблица users, и вы хотите вывести всех пользователей. Код написан по старинке:

$link = mysql_connect('localhost', 'user', 'password');
mysql_select_db('test');

$result = mysql_query("SELECT * FROM users");

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

Вроде бы классика. Но если таблица users не существует, или в SQL синтаксическая ошибка, то mysql_query() вернёт не resource, а false. И тогда mysql_fetch_array() получает boolean вместо resource — отсюда и ошибка.

Чаще всего проблема кроется именно в неудачном выполнении запроса. Но давайте разберём все возможные причины по порядку.

Причина №1: SQL-запрос вернул false

Это самая распространённая ситуация. mysql_query() возвращает false, если запрос не удался. Например:

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

Как проверить? Просто добавьте проверку после запроса:

$result = mysql_query("SELECT * FROM non_existent_table");

if (!$result) {
    die('Ошибка запроса: ' . mysql_error());
}

while ($row = mysql_fetch_array($result)) {
    // ...
}

Это сразу покажет, в чём дело. mysql_error() выдаст текст ошибки, например: "Table 'test.non_existent_table' doesn't exist".

Причина №2: Потеря соединения с БД

Иногда соединение обрывается (например, из-за тайм-аута или перезагрузки MySQL). Тогда mysql_query() тоже вернёт false. Решение — всегда проверять соединение:

$link = mysql_connect('localhost', 'user', 'password');
if (!$link) {
    die('Не удалось подключиться: ' . mysql_error());
}

Но даже это не панацея. Лучше использовать функции, которые умеют автоматически переподключаться — например, MySQLi.

Причина №3: Вы путаете функции mysql_* и mysqli_*

Ещё один частый случай. Вы можете случайно смешивать две разные библиотеки. Например, подключиться через mysqli_connect(), а запрос делать через mysql_query(). Это не сработает: mysql_query() ожидает resource от mysql_connect(), а не от mysqli_connect().

Вот пример путаницы:

// Подключение через MySQLi
$link = mysqli_connect('localhost', 'user', 'password', 'test');

// А запрос через старую mysql_*
$result = mysql_query("SELECT * FROM users"); // Ошибка!

while ($row = mysql_fetch_array($result)) {
    echo $row['name'];
}

Решение — придерживаться одной библиотеки. Либо всё через mysql_* (но не рекомендуется), либо через mysqli_*.

«А зачем вообще нужен resource?» — спросите вы

В PHP resource — это специальный тип, который указывает на внешний ресурс (например, подключение к БД или результат запроса). Старые функции mysql_* работают именно с resource. А современные — с объектами (PDO или MySQLi).

Если вы используете mysql_query(), то при успехе получаете resource. Если ошибка — получаете false. PHP не умеет обрабатывать false как resource, отсюда и предупреждение.

Как исправить раз и навсегда: переходим на PDO

Лучший способ забыть об этой ошибке — перестать использовать функции mysql_*. Они объявлены устаревшими ещё в PHP 5.5 и удалены в PHP 7.0. Если вы пишете на PHP 7 или 8, код с mysql_fetch_array() вообще не заработает.

Вот пример того же самого кода, но на PDO (PHP Data Objects):

try {
    $pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'user', 'password');
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $stmt = $pdo->query("SELECT * FROM users");

    while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
        echo $row['name'] . '<br>';
    }
} catch (PDOException $e) {
    echo 'Ошибка соединения или запроса: ' . $e->getMessage();
}

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

  • Нет ошибок с resource — всё через объекты
  • Автоматическая обработка ошибок через исключения
  • Поддержка разных СУБД (не только MySQL)
  • Безопасность при использовании подготовленных запросов

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

Если вы не хотите переходить на PDO, используйте MySQLi. Он тоже решает проблему с resource, но остаётся в мире MySQL:

$mysqli = new mysqli('localhost', 'user', 'password', 'test');

if ($mysqli->connect_error) {
    die('Ошибка подключения: ' . $mysqli->connect_error);
}

$result = $mysqli->query("SELECT * FROM users");

if ($result) {
    while ($row = $result->fetch_assoc()) {
        echo $row['name'] . '<br>';
    }
} else {
    echo 'Ошибка запроса: ' . $mysqli->error;
}

Обратите внимание: $result->fetch_assoc() — это метод объекта, а не функция. И никаких resource.

Что делать

Блоги

Рекомендаций по книгам