Ошибка "expects parameter 1 to be resource" в mysql_fetch_array() и других функциях
<?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 решит не только текущую проблему, но и сделает ваш код более профессиональным и безопасным в долгосрочной перспективе.
Ответов пока нет.
Войдите чтобы оставить ответ