Глава 54. Использование PHP

В этом разделе собрано множество общих ошибок, которые могут вам встретиться при написании PHP скриптов.

1. Я хочу написать общий PHP скрипт, кторый может обрабатывать данные, приходящие из любой формы. Как узнать какие переменные метода POST доступны?
2. Мне надо преобразовать все одиночные кавычки (') в обратную косую черту с последующей одиночной кавычкой (\'). Как я могу сделать это с помощью регулярного выражения? Я также хотел бы преобразовать " в \" и \ в \\.
3. Все мои " превратились в \" и мои ' в \', как я могу избавиться от всех этих нежелательных обратных косых черт? Как и почему они появились?
4. Когда я делаю следующее, вывод распечатывается не в том порядке:
<?php
function myfunc($argument)
{
    echo
$argument + 10;
}
$variable = 10;
echo
"myfunc($variable) = " . myfunc($variable);
?>
Что происходит?
5. Эй, что произошло с моими строками?
<pre>
<?php echo "This should be the first line."; ?>
<?php
echo "This should show up after the new line above."; ?>
</pre>
6. Я получаю сообщение 'Warning: Cannot send session cookie - headers already sent...' или 'Cannot add header information - headers already sent...'.
7. Мне необходим прямой доступ к информации в заголовке запроса. Как я могу это сделать?
8. Когда я пытаюсь использовать аутентификацию с IIS, я получаю 'No Input file specified'.
9. Windows: У меня нет доступа к файлам, разделяемых другим компьютером, по IIS.
10. Мой PHP скрипт работает в IE и Lynx, а в Netscape некоторый вывод отсутствует. Когда я выполняю "View Source", я вижу содержимое в IE, а в Netscape нет.
11. Как я должен совмещать XML и PHP? Он жалуется на мои <?xml тэги!
12. Как я могу использовать PHP с FrontPage или каким-либо другим редактором HTML, который настаивает на перемещении моего кода?
13. Где я могу найти полный список переменных, доступных мне в PHP?
14. Как я могу генерировать PDF файлы без использования платных или коммерческих библиотек ClibPDF и PDFLib? Я бы хотел что-нибудь бесплатное и не требующее внешних библиотек PDF.
15. Я пытаюсь получить доступ к одной из стандартных CGI переменных (таких как $DOCUMENT_ROOT или $HTTP_REFERER) в определённой пользователем функции и, похоже, она не может быть найдена. В чём дело?
16. Несколько PHP директив могут принимать сокращения для байтовых значений в отличие от только integer байтовах значений. Каковы все доступные сокращения? И могу ли я использовать их вне php.ini?

1. Я хочу написать общий PHP скрипт, кторый может обрабатывать данные, приходящие из любой формы. Как узнать какие переменные метода POST доступны?

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
"None of the POSTed values are empty, posted:\n";
    
var_dump($post);
} else {
    print
"We have " . count($empty) . " empty values\n";
    print
"Posted:\n"; var_dump($post);
    print
"Empty:\n";  var_dump($empty);
    exit;
}
?>

Суперглобальные переменные: замечание о доступности: Начиная с PHP 4.1.0, стали доступными суперглобальные массивы, такие как $_GET, $_POST, $_SERVER и т.д. Дополнительную информацию смотрите в разделе руководства superglobals

2. Мне надо преобразовать все одиночные кавычки (') в обратную косую черту с последующей одиночной кавычкой (\'). Как я могу сделать это с помощью регулярного выражения? Я также хотел бы преобразовать " в \" и \ в \\.

Это делает функция addslashes(). Смотрите также mysql_escape_string(). Также вы можете избавиться от обратной косой черты с помощью stripslashes().

Замечание о директиве: magic_quotes_gpc: Директива PHP magic_quotes_gpc имеет значение по умолчанию on (включена). По сути это применяет функцию addslashes() ко всем вашим GET-, POST-, и COOKIE-данным. Чтобы удалить добавленные косые черты, вы можете использовать stripslashes().

3. Все мои " превратились в \" и мои ' в \', как я могу избавиться от всех этих нежелательных обратных косых черт? Как и почему они появились?

PHP функция stripslashes() удалит эти обратные косые черты из вашей строки (string). Вероятнее всего, обратные косые черты магически появились из-за того, что включена PHP директива magic_quotes_gpc

Замечание о директиве: magic_quotes_gpc: Директива PHP magic_quotes_gpc имеет значение по умолчанию on (включена). По сути это применяет функцию addslashes() ко всем вашим GET-, POST-, и COOKIE-данным. Чтобы удалить добавленные косые черты, вы можете использовать stripslashes().

4. Когда я делаю следующее, вывод распечатывается не в том порядке:
<?php
function myfunc($argument)
{
    echo
$argument + 10;
}
$variable = 10;
echo
"myfunc($variable) = " . myfunc($variable);
?>
Что происходит?

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

5. Эй, что произошло с моими строками?
<pre>
<?php echo "This should be the first line."; ?>
<?php
echo "This should show up after the new line above."; ?>
</pre>

В PHP, блок кода завершается либо с "?>", либо с "?>\n" (где \n означает "новая строка"). В вышеприведённом примере предложения выведутся на одной строке, так как PHP опусткает символ новой строки после завершения блока. Это означает, что вам необходимо вставить дополнительный символ новой строки после каждого блока PHP кода, для того чтобы вывод продолжался с новой строки.

Почему PHP делает это? Потому что при форматировании обычного HTML это, обычно, упрощает вашу жизнь когда вым не нужна эта новая строка и вам не надо создавать невероятно длинные строки для того, чтобы сделать сырой исходник страницы читаемым.

6. Я получаю сообщение 'Warning: Cannot send session cookie - headers already sent...' или 'Cannot add header information - headers already sent...'.

Функциям header(), setcookie(), и функциям сессии нужно добавить заголовки к выходному потоку, но заголовки могут быть посланы только перед всем другим содержимым. Перед использованием этих функций не может быть никакого вывода HTML. Функция headers_sent() проверит если ваш скрипт уже послал заголовки; также смотрите Функции Управления Выводом.

7. Мне необходим прямой доступ к информации в заголовке запроса. Как я могу это сделать?

Это делает функция getallheaders() если вы запускаете PHP как модуль Apache. Так следующий кусок кода покажет вам все заголовки запроса:
<?php
$headers
= getallheaders();
foreach (
$headers as $name => $content) {
    echo
"headers[$name] = $content<br />\n";
}
?>

Также смотрите apache_lookup_uri(), apache_response_headers() и fsockopen()

8. Когда я пытаюсь использовать аутентификацию с IIS, я получаю 'No Input file specified'.

Это недостаток модели безопасности IIS. Проблема общая для всех CGI программ, выполняющихся под IIS. Чтобы обойти проблему, создайте простой HTML файл (неразбираемый PHP) как входную страницу в аутентифицируемой директории. Затем используйте META тэг для перенаправления на PHP страницу или поместите ссылку на PHP страницу. После этого PHP распознает аутентификацию правильно. С модулем ISAPI такой проблемы нет. Это не должно повлиять на другие web сервисы NT. Для дополнительной информации смотрите: http://support.microsoft.com/kb/q160422/ и раздел руководства HTTP Аутентификация.

9. Windows: У меня нет доступа к файлам, разделяемых другим компьютером, по IIS.

Вам необходимо сделать изменения. Идите в Internet Information Services. Найдите ваш PHP файл и перейдите в его свойства. Идите в закладку File Security, Edit -> Anonymous access and authentication control.

Вы можете исправить проблему либо сняв отметку с Anonymous Access и оставив отмеченым Integrated Window Authentication, либо отметив Anonymous Access и отредактировать права пользователя, так как у него может не быть прав.

10. Мой PHP скрипт работает в IE и Lynx, а в Netscape некоторый вывод отсутствует. Когда я выполняю "View Source", я вижу содержимое в IE, а в Netscape нет.

Netscape более строг к HTML тэгам (таким как таблицы), чем IE. Может быть полезно пропустить ваш HTML вывод через HTML validator, такой как validator.w3.org. Например, это может быть вызвано отсутствием </table>.

Также, оба IE и Lynx игнорируют любые NUL-ы (\0) в HTML потоке, а Netscape нет. Лучший способ проверить это - скомпилировать версию командной строки PHP (также известную как CGI версия) и выполнить ваш скрипт из командной строки. На *nix, пропустите вывод через od -c и ищите любые \0 символы. Если вы под Windows, вам надо найти редактор или какую-либо другую программу, которая позволяет просматривать двоичные файлы. Когда Netscape видит NUL в файле, он обычно не будет больше ничего выводить на этой строке, тогда как IE и Lynx будут.

11. Как я должен совмещать XML и PHP? Он жалуется на мои <?xml тэги!

Для того, чтобы встроить <?xml напрямую в ваш PHP код, вам надо отключить короткие тэги, установив PHP директиву short_open_tags в 0. Вы можете установить эту директиву с помощью ini_set(). Независимо от того, что включена или нет short_open_tags, вы можете делать что-то типа: <?php echo '<?xml'; ?>. По умолчанию эта директива включена.

12. Как я могу использовать PHP с FrontPage или каким-либо другим редактором HTML, который настаивает на перемещении моего кода?

Самое простое, что можно сделать - это включить поддержку ASP тэгов в вашем PHP коде. Это позволит вам использовать разделители кода в стиле ASP <% и %>. Некоторые популярные редакторы HTML обращаются с ними более интеллигентно (пока ещё). Чтобы разрешить тэги в стиле ASP, вам надо установить переменную asp_tags в php.ini или использовать соответствующую директиву Apache.

13. Где я могу найти полный список переменных, доступных мне в PHP?

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

register_globals: важное замечание: Начиная с PHP 4.2.0, значением директивы PHP register_globals по умолчанию является off (выключено). Сообщество PHP рекомендует всем не полагаться на эту директиву, а использовать вместо этого иные средства, такие как superglobals.

14. Как я могу генерировать PDF файлы без использования платных или коммерческих библиотек ClibPDF и PDFLib? Я бы хотел что-нибудь бесплатное и не требующее внешних библиотек PDF.

Есть несколько альтернатив, написанных на PHP, таких как http://www.ros.co.nz/pdf/, http://www.fpdf.org/, http://www.gnuvox.com/pdf4php/ и http://www.potentialtech.com/ppl.php. А также модуль Panda.

15. Я пытаюсь получить доступ к одной из стандартных CGI переменных (таких как $DOCUMENT_ROOT или $HTTP_REFERER) в определённой пользователем функции и, похоже, она не может быть найдена. В чём дело?

Важно осознавать, что директива PHP register_globals также затрагивает переменные окружения и сервера. Когда register_globals = off (по умолчанию off, начиная с PHP 4.2.0), default is off since 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.

Суперглобальные переменные: замечание о доступности: Начиная с PHP 4.1.0, стали доступными суперглобальные массивы, такие как $_GET, $_POST, $_SERVER и т.д. Дополнительную информацию смотрите в разделе руководства superglobals

16. Несколько PHP директив могут принимать сокращения для байтовых значений в отличие от только integer байтовах значений. Каковы все доступные сокращения? И могу ли я использовать их вне php.ini?

Доступные опции: K (для Килобайтов), M (для Мегабайтов) и G (для Гигабайтов; доступна начиная с PHP 5.1.0); они чувствительны к регистру. Всё остальное считается байтами. 1M равно одному Мегабайту или 1048576 байтам. 1K равно одному Килобайту или 1024 байтам. Вы не можете использовать эти сокращения вне php.ini, вместо используйте integer значения байтов. Смотрите документацию по ini_get() для примеров как преобразовать эти значения.