Я пытаюсь получить данные из таблицы 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'];
}
Оригинальный вопрос.
Эта ошибка - вторичная. И в правильно спроектированном приложении возникать в принципе не должна.
Она лишь сигнализирует о том, что предыдущая функция, которая выполняла 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() как-то глупо. Но в любом случае, как бы ни обрабатывалась ошибка, она должна следовать двум непреложным правилам:
echo и die()!!! Ошибки базы данных должны всегда транслироваться в ошибки РНР и выводиться туда, куда выводятся все остальные. Если на сайте запрещен вывод ошибок в браузер, то ошибки БД не должны быть исключением из этого правила.Надо прочитать сообщение об ошибке.
Это звучит банальностью, но на удивление никто из неспециалистов раздающих советы никогда этого не упоминает! При том что прочтение текста ошибки помогает в сто раз лучше шаманских телодвижений типа "пересчитайте все кавычки":
Во-первых, mysql сразу скажет, в чем суть ошибки. Если в базе нет таблицы, к которой мы обращаемся, или сервер весь целиком упал, то пересчитывать кавычки бесполезно.
Во-вторых, если ошибка все-таки в синтаксисе, то mysql точно укажет место где её искать - она процитирует кусок запроса, начинающийся сразу за ошибкой.
Если проблема всё-таки в синтаксисе, и при этом вызвана переданными в запрос данными, то Самой Дурацкой Идеей будет "экранировать ваши значения с помощью mysql_real_escape_string()". И уж тем более глупостью будет применять эту функцию для защиты от SQL инъекций. Она не для этого предназначена.
Для того, чтобы навсегда избавиться от любых проблем, связанных с передаваемыми в запрос переменными, необходимо перестать вставлять их в строку запроса напрямую. А делать это только через посредника, называемого "плейсхолдер".
Драйвер для работы с БД через плейсхолдеры можно написать на основе любого API - будь это mysql, mysqli или PDO. Но поскольку, во-первых, для этого нужно обладать специальными знаниями, а во-вторых начинающие пользователи РНР до ужаса боятся любых готовых библиотек, предпочитая пользоваться лишь встроенными средствами языка, то у них остаётся только один выбор - PDO.
Как и 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();
}
}
Сборка персонального компьютера от Artline: умный выбор для современных пользователей