Ошибки, выдаваемые php, содержат не только слова "Warning" и "Fatal error", в них есть и текст ошибки, который прямым текстом говорит о причине своего появления. Правда, на английском языке.
Также часто информацию о причинах ошибки можно найти в официальной документации (php.net, если кто-то еще не знает), правда, и она по большей части на английском.
А так как не смотря ни на что просьбы о помощи появляются регулярно, и помощникам откровенно задолбалось из раза в раз повторять одно и то же, ниже я предлагаю собрать коллекцию часто задаваемых вопросов, просьб, проблем и т.п., чтобы вместо очередного "Бла-бла" давать ссылку сюда.
Ожидаю участие всех: от обычных пользователей до администрации.
P.S. Слова о "ненужности" и т.д. не принимаю - faq нужен. Будем его делать.
Содержание:
- 1. Warning: mysql_fetch_array()/или mysql_fetch_assoc()/mysql_fetch_row(): supplied argument is not a valid MySQL result resource in %script_address% on line %line_num%
- 2. 1064 - You have an error in your SQL syntax
- 3. Cannot modify header information - headers already sent
- 4. session_start() [function.session-start]: Cannot send session cookie
- 5. Parse error: syntax error, unexpected $end in %script_address% on line %line_num%
- 6. Обработка данных
- 7. Динозавры или "использую ereg*, HTTP_*_VARS, а надо мной все смеются"
- 8. Кракозябры при выводе из MySQL
- Благодарности
Свернутый текст
Для начала кое-что поясню. Функция mysql_query(), которой вы делаете запрос, может вернуть два значения: указатель на результаты запроса или ресурс (точнее - дескриптор), далее с помощью этого указателя можно вытаскивать непосредственно строки из базы данных. В случаи же, если произошла какая-то ошибка*, функция вернет false.
* Следует заметить, что имеется в виду ошибка синтаксиса в запросе. Если же в бд нет строк, удовлетворяющих запросу, все равно вернется ресурс.
Только ленивый не знает, что функция mysql_fetch_array в качестве параметра принимает именно ресурс, а следовательно, результатом появления описанной ошибки является неверный синтаксис. Узнать, что именно не так в запросе, можно таким способом:
Опыт показывает, что чаще других появляется ошибка, описанная в следующем пункте.
Совет.
Используйте функцию mysql_fetch_assoc вместо mysql_fetch_array, т.к. последняя в общем случаи возвращает лишний массив, а к оперативной памяти надо относится бережно и загружать в нее только то, что действительно необходимо.
* Следует заметить, что имеется в виду ошибка синтаксиса в запросе. Если же в бд нет строк, удовлетворяющих запросу, все равно вернется ресурс.
Только ленивый не знает, что функция mysql_fetch_array в качестве параметра принимает именно ресурс, а следовательно, результатом появления описанной ошибки является неверный синтаксис. Узнать, что именно не так в запросе, можно таким способом:
$sql = "..."; // Текст запрос
// В случаи ошибки сценарий прекратит выполнение и выведет на экран текст ошибки.
// Эту ошибку возвращает уже сама бд.
$query = [SPAN=darling]mysql[/SPAN]_query($sql) or die("Error in SQL:<pre>$sql</pre>". [SPAN=darling]mysql[/SPAN]_error());
Опыт показывает, что чаще других появляется ошибка, описанная в следующем пункте.
Совет.
Используйте функцию mysql_fetch_assoc вместо mysql_fetch_array, т.к. последняя в общем случаи возвращает лишний массив, а к оперативной памяти надо относится бережно и загружать в нее только то, что действительно необходимо.
Вопрос №2: 1064 - You have an error in your SQL syntax
Свернутый текст
Для того, чтобы понять, что же не так в запросе, надо его увидеть. Для этого рекомендуется все сложные запросы выделять в отдельную переменную - это облегчает отработку ошибок в приложении:
Дальше придется смотреть глазами и вспоминать, как должен выглядеть запрос.
В данном примере пропущены кавычки.
Совет.
Бывает так, что найти ошибку в запросе (особенно в сложном запросе) довольно затруднительно. В этом случаи рекомендую разбивать запрос на несколько строк, ведь в сообщении бд есть указание строки, в которой допущена ошибка:
Теперь в конце сообщения мы увидем номер строки: "You have ... at line 4", а это сильно сужает круг поиска.
$sql = "INSERT INTO `tbl` (`user_name`, `user_age`) VALUES ($user_name, $user_age)";
// Выводим запрос с подставленными переменными
// и станавливаем выполнение сценария
$query = [SPAN=darling]mysql[/SPAN]_query($sql) or die("Error in SQL:<pre>$sql</pre>". [SPAN=darling]mysql[/SPAN]_error());
Дальше придется смотреть глазами и вспоминать, как должен выглядеть запрос.
В данном примере пропущены кавычки.
Совет.
Бывает так, что найти ошибку в запросе (особенно в сложном запросе) довольно затруднительно. В этом случаи рекомендую разбивать запрос на несколько строк, ведь в сообщении бд есть указание строки, в которой допущена ошибка:
$sql = "INSERT INTO `tbl`
(`user_name`, `user_age`)
VALUES
($user_name, $user_age)";
Теперь в конце сообщения мы увидем номер строки: "You have ... at line 4", а это сильно сужает круг поиска.
Вопрос №3: Cannot modify header information - headers already sent
Вопрос №4: session_start() [function.session-start]: Cannot send session cookie
Свернутый текст
Немного теории. На запрос браузера сервер отвечает в два этапа: первым отправляется заголовок с информацией о странице (статус ответа, кодировка, значения устанавливаемых кукисов (!) и многое другое), а уж только затем отправляется само содержание страницы (обычно - html код).
По этой причине модификация заголовка (с помощью функций header и в частности setcookie) возможна только до того, как скрипт отправит в поток какой-либо символ, даже если пробел.
Таким образом, описанная ошибка может появится в двух случаях:
1. Ошибка логики приложения: вы сначала отправляете html-код (например, начало разметки), а потом пытаетесь поставть кукисы:
2. Программист случайно поставил пробел или перенос строки в самое начало файла:
3. Файл сохранен в кодировке "UTF-8 with BOM". PHP не имеет корректно работать с этим самым "BOM", кодировка должна быть UTF-8 без BOM.
Совет.
Вот пример полного сообщения об ошибке:
По этой причине модификация заголовка (с помощью функций header и в частности setcookie) возможна только до того, как скрипт отправит в поток какой-либо символ, даже если пробел.
Таким образом, описанная ошибка может появится в двух случаях:
1. Ошибка логики приложения: вы сначала отправляете html-код (например, начало разметки), а потом пытаетесь поставть кукисы:
<html>
<head>
<title>Тут модный заголовок</title>
</head>
<body>
<?[SPAN=darling]php[/SPAN]
/*
* Открываем сессию для наших любимых пользователей
*/
session_start();
/*
* Блин, я забыл указать кодировку страницы, ну да ладно
* Я ее отправлю в заголовке, круче будет!
*/
header("Content-type: text/html; charset=utf-8");
echo 'WTF';
2. Программист случайно поставил пробел или перенос строки в самое начало файла:
*я пробел* <?[SPAN=darling]php[/SPAN]
session_start();
3. Файл сохранен в кодировке "UTF-8 with BOM". PHP не имеет корректно работать с этим самым "BOM", кодировка должна быть UTF-8 без BOM.
Совет.
Вот пример полного сообщения об ошибке:
Цитата |
Warning: Cannot modify header information - headers already sent by (output started at W:\home\localhost\www\test\index.php:6) in W:\home\localhost\www\test\index.php on line 15 |
Обратите внимание на информацию в скобках. Дословно: "заголовки были отправлены было в W:\home\localhost\www\test\index.php:6", где последняя цифра - номер строки, где появился "левый" символ, который вынудил сервер отправить заголовок.
Вопрос №5: syntax error, unexpected $end in %script_address% on line %line_num%
Свернутый текст
В большинстве случаев это означает одно: программист забыл закрыть фигурную скобку.
Интерпритатор посчитает, что последняя закрывающаяся скобка относится к выражению ($d == 0), но ведь и ($d > 0) надо закрыть.
Стоит заметить, что в качестве строки php скорее всего укажет на строку, которой в файле даже нет (говоря точнее: максимальная строка + 1). Можно это расценить как надежду PHP до последнего встретить эту закрывающую скобку.
Тут ваш лучших помощник - редактор с подсветкой, который умеет искать парные скобки, отступы в коде и ваша внимательность.
Совет.
Как уже было сказано, отступы имеют важное значение в понимании кода и в поиске ошибок:
Правда, стоит признать, что в поиске парных скобок никакая внимательность не сравнится с хорошим редактором.
if ($d > 0) {
$d *= 5;
if ($d == 0) {
$d -= 13;
}
Интерпритатор посчитает, что последняя закрывающаяся скобка относится к выражению ($d == 0), но ведь и ($d > 0) надо закрыть.
Стоит заметить, что в качестве строки php скорее всего укажет на строку, которой в файле даже нет (говоря точнее: максимальная строка + 1). Можно это расценить как надежду PHP до последнего встретить эту закрывающую скобку.
Тут ваш лучших помощник - редактор с подсветкой, который умеет искать парные скобки, отступы в коде и ваша внимательность.
Совет.
Как уже было сказано, отступы имеют важное значение в понимании кода и в поиске ошибок:
if ($d > 0) {
$d = $d - 5;
if ($d == 0) {
$d *= 5;
if ($d > 0) {
$d -= 13;
}
} else if ($d < 0) {
$d = -$d;
}
Правда, стоит признать, что в поиске парных скобок никакая внимательность не сравнится с хорошим редактором.
Вопрос №6: "Как обрабатывать данные, приходящие от пользователя?", "А как обрабатывать данные, отдаваемые пользователю?"
Свернутый текст
Если ответ нужен здесь и сейчас, то вкратце:
1. Данные пользователя должны хранится именно в том виде, в котором их ввел пользователь. То есть, никаких модификаций. Запомните это.
2. Бывает так, что в тексте пользователя встречаются кавычки, и если подставить такие данные в запрос - как минимум, база данных отвергнет запрос и вернет ошибку. В худшем случаи - это будет сделано специально, с целью навредить. Читать подробнее про sql-инъекции.
Уберечься от этого можно следующим способом: если данные представляют собой строку, то их следует обработать функцией mysql_real_escape_string, которая экранирует кавычки, если же данные - это числа, то их следует привести к соответствующему формату:
Обратите внимание на запрос: числовые данные не обрамляются кавычками.
3. При выводе, дабы сохранить целостность html-разметки и максимально уберечь от всяких пакостей, данные следует обрабатывать функией htmlspecialchars():
Тем, кто действительно хочет чему-то научиться, разобраться в тонкостях работы с данными, рекомендую решить [URL=http://phpforum.ru/index.php?showtopic=19168'>вот эту</a> задачу. Будем рады оценить ваш вариант.
1. Данные пользователя должны хранится именно в том виде, в котором их ввел пользователь. То есть, никаких модификаций. Запомните это.
2. Бывает так, что в тексте пользователя встречаются кавычки, и если подставить такие данные в запрос - как минимум, база данных отвергнет запрос и вернет ошибку. В худшем случаи - это будет сделано специально, с целью навредить. Читать подробнее про sql-инъекции.
Уберечься от этого можно следующим способом: если данные представляют собой строку, то их следует обработать функцией mysql_real_escape_string, которая экранирует кавычки, если же данные - это числа, то их следует привести к соответствующему формату:
$user_name = [SPAN=darling]mysql[/SPAN]_real_escape_string($_POST['user_name']);
$user_age = (int) $_POST['user_age'];
$sql = "INSERT INTO `tbl` (`user_name`, `user_age`) VALUES ('$user_name', $user_age)";
$query = [SPAN=darling]mysql[/SPAN]_query($sql);
Обратите внимание на запрос: числовые данные не обрамляются кавычками.
3. При выводе, дабы сохранить целостность html-разметки и максимально уберечь от всяких пакостей, данные следует обрабатывать функией htmlspecialchars():
$sql = "SELECT * FROM `tbl` LIMIT 1";
$query = [SPAN=darling]mysql[/SPAN]_query($sql);
$arr = [SPAN=darling]mysql[/SPAN]_fetch_assoc($query);
// На случай, если имя пользователя содержит < или >
echo 'Имя пользователя:'. htmlspecialchars($arr['user_name']);
// Числовые данные обрабатывать дополнительно смысла нет
echo 'Возраст:'. $arr['user_age'];
Тем, кто действительно хочет чему-то научиться, разобраться в тонкостях работы с данными, рекомендую решить [URL=http://phpforum.ru/index.php?showtopic=19168'>вот эту</a> задачу. Будем рады оценить ваш вариант.
Вопрос №7: использую ereg*, HTTP_*_VARS, а надо мной все смеются
Свернутый текст
Потому что вы используйте устаревшие функции. Их немало. Список таких функций можно найти, например, здесь.
Вопрос №8: strpos, strlen и прочие str* работают некорректно с русскими буквами
Свернутый текст
Скорее всего, вы используете многобайтовую кодировку (например, UTF-8), для работы с которыми в php.ini необходимо подключить расширение php_mbstring.dll (Multibyte String, список функций).
Благодарности
За участие в создании faq объявляется благодарность kirik'у, inpost'y, alex12060, Trianon'у и twin'y:)