В этом разделе собрано множество общих ошибок, которые могут вам встретиться при написании PHP скриптов.
PHP - это клей, который скрепляет вместе сотни различных внешних библиотек, поэтому иногда это кажется довольно запутанным. Однако, общее правило таково:
Параметры функций работы с массивами упорядочены в виде "иголка (needle), сено (haystack)", тогда как порядок в строковых функциях обратный, то есть аналогичен "сено, иголка".
PHP предлагает множество предопределенных переменных, таких как суперглобальная $_POST. Вы можете пройтись по $_POST так как это ассоциативный массив всех значений, пришедших с POST. Для примера, давайте просто пройдемся по ним с foreach, проверим на пустые (empty()) значения и распечатаем.
<?php
$empty = $post = array();
foreach ($_POST as $varname => $varvalue) {
if (empty($varvalue)) {
$empty[$varname] = $varvalue;
} else {
$post[$varname] = $varvalue;
}
}
print "<pre>";
if (empty($empty)) {
print "В POST не было пустых значений, вот что там было:\n";
var_dump($post);
} else {
print "Пришло " . count($empty) . " пустых значений\n";
print "Всего отправлено:\n"; var_dump($post);
print "Пустых:\n"; var_dump($empty);
exit;
}
?>
Подразумевая, что вы хотите использовать результат преобразования в работе с базой данных, используйте соответствующий механизм экранирования, идущий с используемой вами базой данных. Например, используйте mysql_real_escape_string() с MySQL и pg_escape_string() с PostgreSQL. Есть также более общие функции addslashes() и stripslashes(), они часто встречаются в старом PHP-коде.
Замечание: Замечание о директиве: magic_quotes_gpc
Директива PHP magic_quotes_gpc имеет значение по умолчанию on (включена). По сути это применяет функцию addslashes() ко всем GET-, POST- и COOKIE-данным. Чтобы удалить добавленные слеши, вы можете использовать stripslashes().
Наиболее частая причина магического появления обратных слешей - это включенная PHP-директива magic_quotes_gpc. Этот функционал PHP уже устарел и на него нельзя полагаться, поэтому эту директиву рекомендуется отключить. Кроме того, для удаления обратных слешей из строк можно использовать функцию stripslashes().
Замечание: Замечание о директиве: magic_quotes_gpc
Директива PHP magic_quotes_gpc имеет значение по умолчанию on (включена). По сути это применяет функцию addslashes() ко всем GET-, POST- и COOKIE-данным. Чтобы удалить добавленные слеши, вы можете использовать stripslashes().
Данная возможность была помечена УСТАРЕВШЕЙ начиная с версии PHP 5.3.0 и была УДАЛЕНА в версии PHP 5.4.0.
Во-первых, следует объяснить что делает эта директива. Скажем, используется вот такой URL: http://example.com/foo.php?animal=cat и в foo.php у нас находится следующий PHP-код:
<?php
// Использование $_GET в данном случае более предпочтительно
echo $_GET['animal'];
// Чтобы переменная $animal была определена, директива register_globals должна
// быть включена.
// НЕ ДЕЛАЙТЕ ЭТОГО!
echo $animal;
// Это касается всех переменных, включая $_SERVER
echo $_SERVER['PHP_SELF'];
// Опять-таки, чтобы $PHP_SELF была определена, надо включить register_globals
// НЕ ДЕЛАЙТЕ ЭТОГО!
echo $PHP_SELF;
?>
Код выше демонстрирует как register_globals создает множество переменных. Годами такой стиль написания не одобрялся и годами register_globals была выключена по умолчанию. Несмотря на то, что большинство хостингов отключает register_globals, осталось еще много устаревших статей, руководств и книг, которые требуют включения этой директивы. Действуйте соответственно.
См. также следующие источники за дополнительной информацией:
Замечание:
В примере выше мы использовали URL, который содержал QUERY_STRING. Передача информации подобным образом происходит с помощью метода HTTP GET, вот почему мы использовали суперглобальный массив $_GET.
<?php
function myfunc($argument)
{
echo $argument + 10;
}
$variable = 10;
echo "myfunc($variable) = " . myfunc($variable);
?>
Для того, чтобы использовать результат вашей функции в выражении (таком как соединение с другими строками, как в вышеприведенном примере), вам необходимо вернуть значение с помощью return, а не выводить его через echo.
<pre>
<?php echo "Это должно быть на первой строке."; ?>
<?php echo "А это должно быть на следующей строке."; ?>
</pre>
В PHP, блок кода завершается либо с "?>", либо с "?>\n" (где \n означает "новая строка"). В вышеприведенном примере предложения выведутся на одной строке, так как PHP опускает символ новой строки после завершения блока. Это означает, что вам необходимо вставить дополнительный символ новой строки после каждого блока PHP кода, для того чтобы вывод продолжался с новой строки.
Почему PHP делает это? Потому что при форматировании обычного HTML это, обычно, упрощает вашу жизнь когда вам не нужна эта новая строка и вам не надо создавать невероятно длинные строки для того, чтобы сделать исходник страницы читаемым.
Функциям header(), setcookie(), и функциям сессии нужно добавить заголовки к выходному потоку, но заголовки могут быть посланы только перед всем другим содержимым. Перед использованием этих функций нельзя ничего выводить, в том числе HTML. Функция headers_sent() проверит, если ваш скрипт уже послал заголовки; также смотрите функции управления выводом.
Это делает функция getallheaders(), если вы запускаете PHP как модуль Apache. Так, следующий кусок кода покажет вам все заголовки запроса:
<?php
$headers = getallheaders();
foreach ($headers as $name => $content) {
echo "headers[$name] = $content<br />\n";
}
?>
Также смотрите apache_lookup_uri(), apache_response_headers() и fsockopen()
Это недостаток модели безопасности IIS. Проблема общая для всех CGI программ, выполняющихся под IIS. Чтобы обойти проблему, создайте простой HTML файл (необрабатываемый PHP) как входную страницу в аутентифицируемой директории. Затем используйте META тэг для перенаправления на PHP страницу или поместите ссылку, указывающую на PHP страницу. После этого PHP распознает аутентификацию правильно. С модулем ISAPI такой проблемы нет. Это не должно повлиять на другие веб-серверы NT. Для дополнительной информации смотрите: » http://support.microsoft.com/kb/q160422/ и раздел руководства HTTP Аутентификация.
Вам необходимо сделать изменения. Идите в Internet Information Services. Найдите ваш PHP файл и перейдите в его свойства. Идите в закладку File Security, Edit -> Anonymous access and authentication control.
Вы можете исправить проблему либо сняв отметку с Anonymous Access и оставив отмеченным Integrated Window Authentication, либо отметив Anonymous Access и отредактировать права пользователя, так как у него может не быть прав.
Для того, чтобы встроить <?xml напрямую в ваш PHP код, вам надо отключить короткие тэги, установив PHP директиву short_open_tags в 0. Вы можете установить эту директиву с помощью ini_set(). Независимо от того, включена short_open_tags или нет, вы можете делать что-то типа: <?php echo '<?xml'; ?>. По умолчанию эта директива включена (On).
Читайте страницу руководства по предопределенным переменным, так как она содержит частичный список предопределенных переменных, доступных вашему скрипту. Полный список доступных переменных (и множество другой информации) можно увидеть, вызвав функцию phpinfo(). Не забудьте прочитать раздел руководства по переменным, лежащим вне PHP так как он описывает общие сценарии для внешних переменных, таких как HTML форма, Cookie и URL.
Замечание: register_globals: важное замечание
Начиная с PHP 4.2.0, значением директивы PHP register_globals по умолчанию является off (выключено). Сообщество PHP рекомендует не полагаться на эту директиву, а использовать вместо этого иные средства, такие как superglobals.
Есть несколько альтернатив, написанных на PHP, таких как » FPDF и » TCPDF.
Есть также расширение Haru, использующее внешнюю свободную библиотеку libHaru.
Важно осознавать, что директива PHP register_globals также затрагивает переменные окружения и сервера. Когда register_globals = off (по умолчанию off, начиная с PHP 4.2.0), $DOCUMENT_ROOT не будет существовать. Вместо нее используйте $_SERVER['DOCUMENT_ROOT']. Если register_globals = on, то переменные $DOCUMENT_ROOT и $GLOBALS['DOCUMENT_ROOT'] будут также существовать.
Если вы уверены, что register_globals = on и удивляетесь почему $DOCUMENT_ROOT недоступна внутри функции, то это потому, что, как любые другие переменные, она требует global $DOCUMENT_ROOT внутри функции. Также смотрите страницу руководства по области определения переменных. Рекомендуется работать с register_globals = off.
Доступные опции: K (для килобайт), M (для мегабайт) и G (для гигабайт; доступна начиная с PHP 5.1.0); они регистронезависимы. Все остальное считается байтами. 1M равно одному мегабайту или 1048576 байтам. 1K равно одному килобайту или 1024 байтам. Эти сокращения вы можете использовать в php.ini и в функции ini_set().
Замечание: килобайт и кибибайт
В нотации PHP один килобайт равен 1024 байтам, тогда как стандарт IEC считает это кибибайтом. В итоге: k и K = 1024 байта.
До версии PHP 5.3.4, существовала ошибка в коде резолвинга доменного имени, не дававшая определить адрес localhost при включенном IPv6, во всех ситуациях связанных с потоками. Для обхода этой проблемы можно использовать "127.0.0.1" или отключить резолвинг IPv6 в файле hosts.