mysql_fetch_array() expects parameter 1 to be resource (or mysqli_result), boolean given

1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд
Загрузка...

Я пытаюсь получить данные из таблицы MySQL, но вылезает одна из этих ошибок:

mysql_fetch_array() expects parameter 1 to be resource, boolean given

или

mysqli_fetch_array() expects parameter 1 to be mysqli_result, boolean given

Вот мой код:

$username = $_POST['username'];
$password = $_POST['password'];
$result = mysql_query("SELECT * FROM Users WHERE UserName LIKE $username");

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

Оригинальный вопрос.


3 ответа
3

 

Как избежать такой ошибки

Эта ошибка — вторичная. И в правильно спроектированном приложении возникать в принципе не должна.

Она лишь сигнализирует о том, что предыдущая функция, которая выполняла SQL запрос, окончилась неудачей, но при этом о причине неудачи никакой информации не несёт.

Чтобы таких ошибок в коде не возникало, необходимо проверять результат той самой предыдущей функции, выполнявшей SQL запрос. Но делать это надо с умом, а не так, как советуют неспециалисты, десятилетиями переписывая друг у друга один и тот же код, не понимая его смысла и не сталкиваясь с результатами его работы (весьма плачевными) на практике.

Вызывая функцию mysql_query(), необходимо всегда проверять результат её работы. И если функция вернула не корректный ресурс, а пустоту, то необходимо, во-первых, получить от mysql сообщение об ошибке, а во-вторых, транслировать его в ошибку РНР (это принципиальный момент, которого начинающие пользователи РНР не понимают поголовно). А в-третьих, очень полезно бывает добавить в сообщение об ошибке сам запрос.

За первое отвечает функция mysql_error(), за второе — trigger_error(), а для третьего необходимо всегда сначала присваивать запрос переменной. Таким образом, любой вызов mysql_query() должен выглядеть так:

$sql = "SELECT ...";
$res = mysql_query($sql) or trigger_error(mysql_error()." in ". $sql);

Таким образом, при возникновении ошибки исполнения запроса, пользователь РНР будет немедленно проинформирован точно так же, как о любых других возникающих в работе скрипта ошибках. А до ошибки «expects parameter» дело уже не дойдет.

В принципе, ещё лучше чем trigger_error(), было бы бросить исключение. Но поскольку

  • throw new Exception() не подставишь так красивенько через or в ту же строку;
  • начинающие пользователи РНР очень плохо представляют себе механизм исключений и тут же начинают использовать его неправильно;
  • расширение mysql уже потеряло всякий смысл, а два оставшихся — mysqli и PDO умеют транслировать ошибки БД в исключения автоматически,

то предлагать исключения для mysql_query() как-то глупо. Но в любом случае, как бы ни обрабатывалась ошибка, она должна следовать двум непреложным правилам:

  1. Никаких echo и die()!!! Ошибки базы данных должны всегда транслироваться в ошибки РНР и выводиться туда, куда выводятся все остальные. Если на сайте запрещен вывод ошибок в браузер, то ошибки БД не должны быть исключением из этого правила.
  2. Сообщение об ошибке обязательно должно содержать имя файла и строку, в которой произошла ошибка, а по возможности — ещё и трассировку вызовов.

Как исправить ошибку.

Надо прочитать сообщение об ошибке.

Это звучит банальностью, но на удивление никто из неспециалистов раздающих советы никогда этого не упоминает! При том что прочтение текста ошибки помогает в сто раз лучше шаманских телодвижений типа «пересчитайте все кавычки»:

Во-первых, mysql сразу скажет, в чем суть ошибки. Если в базе нет таблицы, к которой мы обращаемся, или сервер весь целиком упал, то пересчитывать кавычки бесполезно.
Во-вторых, если ошибка все-таки в синтаксисе, то mysql точно укажет место где её искать — она процитирует кусок запроса, начинающийся сразу за ошибкой.

Как раз и навсегда избавиться от ошибок синтаксиса, вызванных данными.

Если проблема всё-таки в синтаксисе, и при этом вызвана переданными в запрос данными, то Самой Дурацкой Идеей будет «экранировать ваши значения с помощью mysql_real_escape_string()«. И уж тем более глупостью будет применять эту функцию для защиты от SQL инъекций. Она не для этого предназначена.

Для того, чтобы навсегда избавиться от любых проблем, связанных с передаваемыми в запрос переменными, необходимо перестать вставлять их в строку запроса напрямую. А делать это только через посредника, называемого «плейсхолдер».

Драйвер для работы с БД через плейсхолдеры можно написать на основе любого API — будь это mysql, mysqli или PDO. Но поскольку, во-первых, для этого нужно обладать специальными знаниями, а во-вторых начинающие пользователи РНР до ужаса боятся любых готовых библиотек, предпочитая пользоваться лишь встроенными средствами языка, то у них остаётся только один выбор — PDO.

Mysqli

Как и mysql, расширение mysqli на самом деле представляет из себя набор низкоуровневых функций, не предназначенных для использования в коде приложения. Как любой низкоуровневый инструмент, mysqli предоставляет больше возможностей по настройке различных тонкостей, но при этом требует огромное количество кода для самых тривиальных операций. И в первую очередь это касается обработки плейсхолдеров. Поэтому пользоваться функиями mysqli напрямую нельзя, а надо на их основе писать высокоуровневую библиотеку.

Чтобы транслировать ошибки базы данных в ошибки РНР, в mysqli не нужно проверять результат каждой функции. Вместо этого достаточно перед коннектом написать вот такую строчку:

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

и тогда все ошибки БД будут порождать исключения РНР, которые по умолчанию становятся фатальными ошибками РНР, чего для начинающих более чем достаточно.

Откуда берётся ошибка

Эта ошибка возникает, если запрос не может быть выполнен. Функции, которые могут к ней привести:

  • mysql_fetch_array/mysqli_fetch_array()
  • mysql_fetch_assoc()/mysqli_fetch_assoc()
  • mysql_num_rows()/mysqli_num_rows()

Если с запросом всё в порядке, и просто результат его выполнения пустой, то ошибка не возникает. К ошибке приводит только неверный синтаксис SQL.

Как найти источник ошибки

  • Убедитесь, что на сервере, на котором вы ведёте разработку, включено отображение всех ошибок. Вы можете включить его из PHP, выполнив error_reporting(-1); (можно разместить этот код в конфигурационном файле вашего сайта, например). Если при попытке выполнения запроса будут обнаружены ошибки в синтаксисе, то они будут отображены.

  • Используйте mysql_error(). Эта функция вернёт строку с текстом ошибки, если таковая возникла при выполнении последнего запроса.

    Например:

    mysql_connect($host, $username, $password) or die("Ошибка подключения");
    mysql_select_db($db_name) or die("Ошибка выбора БД");
    
    $sql = "SELECT * FROM table_name";
    $result = mysql_query($sql);
    
    if ($result === false) {
        echo mysql_error();
    }
    
  • Выполните ваш запрос в командной строке MySQL или из инструмента вроде phpMyAdmin. Если в запросе есть синтаксическая ошибка, то она будет отображена.

  • Убедитесь, что в запросе верно расставлены кавычки. Это частая причина синтаксических ошибок.

  • Убедитесь, что вы экранируете ваши значения. Если в строке присутствует кавычка, это может привести к ошибке (а также сделать ваш код уязвимым к SQL-инъекциям). Используйте для этого mysql_real_escape_string().

  • Убедитесь, что вы не используете одновременно функции mysqli_* и mysql_*. Их использование нельзя смешивать. (Если вы не знаете, что выбрать, отдайте предпочтение mysqli_*.)

Советы

Не используйте функции mysql_* в новом коде. Разработчики PHP больше не поддерживают и не развивают их, они отмечены как устаревшие, и в будущих версиях будут удалены. Ознакомьтесь с понятием prepared statement и переходите на использование PDO (PHP Data Objects) или MySQLi (MySQL improved). Это избавит вас от проблем с экранированием значений и убережёт от SQL-инъекций.

И MySQLi, и PDO поддерживают режим, в котором при ошибках выбрасываются исключения. В новом коде следует использовать этот подход, потому что он помогает обрабатывать ошибки в одном месте, а не размазывать проверки по всему коду, и позволяет обработке ошибок не зависеть от внешних условий (от конфигурации).

Сравнение возможностей PDO и MySQLi. Если вкратце, то PDO — это общий слой над базами данных, который позволяет относительно легко переключать СУБД; а MySQLi даёт доступ к некоторым дополнительным возможностям СУБД MySQL.

Преимущественно перевод ответа.

$username = $_POST['username'];
$password = $_POST['password'];

if ($result = mysql_query("SELECT * FROM Users WHERE UserName LIKE $username") and mysql_num_rows($result)){
   while($row = mysql_fetch_assoc($result))
   {
      echo $row['FirstName'];
   }
}else{
   if (!mysql_num_rows($result)){
      echo "empty result";
   }else{
      echo mysql_error();
   }
}

Вам также может быть интересно:

Drag and Drop UWP — c# xaml mvvm
Вопрос: Нужно иметь возможность добавлять изображения в приложение путем перетаскивания из файловой системы У Grid включил AllowDrop. Но как добавить перетаскиваемые изображения в коллекцию? Т.к. те ...
Растягивание Высоты , Резина — html css html5
Вопрос: Здравствуйте! Реализовал резиновый дизайн. Растягивается ширина, но длина по % не растягивается. Возможно ли это реализовать? Или так и задумано, растягивание только на ширину ...
Jquery position().left Как быть на мобильниках? — javascript jquery css
Вопрос: На мобильных устройствах, если зумишь экран, position всегда разный. $('g').position().left Как сделать так, чтобы он не менял свои значения? Автор вопроса: ...
Jquery position().left Как быть на мобильниках? — javascript jquery css
Вопрос: На мобильных устройствах, если зумишь экран, position всегда разный. $('g').position().left Как сделать так, чтобы он не менял свои значения? Автор вопроса: ...
requestAnimation и очередность отрисовки — javascript canvas
Вопрос: Здравствуйте! Реализовал 2D игру и в Edge работает все плавно и круто, но в Firefox'e подвисает, сказали, что нужно сделать, чтобы раз-два момент и все ...
Контекстное/всплывающее меню в Android — java android popup
Вопрос: Есть ли техническая возможность сделать приложение, добавляющее свое контекстное или всплывающее меню в любом месте системы? Хочу, чтобы при выделении любого текста появлялась дополнительная кнопка ...
Контекстное/всплывающее меню в Android — java android popup
Вопрос: Есть ли техническая возможность сделать приложение, добавляющее свое контекстное или всплывающее меню в любом месте системы? Хочу, чтобы при выделении любого текста появлялась дополнительная кнопка ...
Завершить службы циклом — c# windows-service
Вопрос: Можно ли остановить службы циклом? У меня есть список служб, занёс их в List List<string> name = new List<string> { "AdobeARMservice", "RemoteRegistry", "TermService", "Messenger", "SSDPSRV", ...
Завершить службы циклом — c# windows-service
Вопрос: Можно ли остановить службы циклом? У меня есть список служб, занёс их в List List<string> name = new List<string> { "AdobeARMservice", "RemoteRegistry", "TermService", "Messenger", "SSDPSRV", ...
RecyclerView — разная разметка — android recyclerview
Вопрос: Смотрел, я смотрел в сторону RecyclerView и наконец решил кинуть ListView и на тебе! В "плохом прошлом" мой ListView использовался для двух разметок. Сейчас я ...
RecyclerView — разная разметка — android recyclerview
Вопрос: Смотрел, я смотрел в сторону RecyclerView и наконец решил кинуть ListView и на тебе! В "плохом прошлом" мой ListView использовался для двух разметок. Сейчас я ...
Как правильно передать массив аргументом для пользовательской функции — php
Вопрос: Если не брать в функцию все это, тогда результат работает. А если вот так в функции все выполнять, тогда PHP ругается: «Invalid ...
Как правильно передать массив аргументом для пользовательской функции — php
Вопрос: Если не брать в функцию все это, тогда результат работает. А если вот так в функции все выполнять, тогда PHP ругается: «Invalid ...
ViewPager внутри ViewPager — такие матрешки работают? — android viewpager
Вопрос: Доброго времени суток. Назрела новая задача. Есть каталог мастеров. При выборе конкретного мастера открывается его страница (активити с ViewPager), и теперь мастеров можно перелистывать свайпом. ...
Почему id всегда 1 Yii2 — yii авторизация
Вопрос: Использую все как по документации. Для получения информации о пользователе использую $identity = $model->findOne(]); И каким бы не был email, id пользователя всегда ...

Оставьте ответ

Ваш e-mail не будет опубликован. Обязательные поля помечены *