2.8 Формы PHP

Передача данных командной строки
Вначале хотим вас поздравить: сейчас мы уже знаем достаточно, чтобы начать писать простейшие сценарии на PHP типа “Hello, world: сейчас 10 часов утра”. Однако нашим сценариям будет недоставать одного — интерактивного взаимодействия с пользователем. Поставим перед собой задачу написать сценарий, который принимает в параметрах две величины: зарегистрированное имя и пароль. Если зарегистрированное имя равно root, а пароль — Z10N0101, следует напечатать: “Доступ открыт для пользователя <имя>” и заблокировать сервер (т. е. вывести стандартный экран “Блокировка” с запросом пароля для разблокирования). Если же данные неверны, необходимо вывести сообщение “Доступ закрыт!”.
Сначала рассмотрим наиболее простой способ передачи параметров сценарию — непосредственный набор их в URL после знака ? — например, в формате login=имя&password=пароль
Итак, пусть у нас на сервере в корневом каталоге есть сценарий на PHP под названием hello.php. Наш сценарий распознает два параметра: login и password. Таким образом, если мы зададим в адресной строке браузера
http://localhost:4000/hello.php?login=root&password=Z10N0101
то должны получить требуемый результат.
Но прежде бывает полезно решить аналогичную, но более простую задачу. Итак, как же нам в сценарии получить строку параметров, переданную после знака вопроса в URL при обращении к сценарию? Для этого можно проанализировать переменную окружения QUERY_STRING, которая в PHP доступна под именем $_SERVER[‘QUERY_STRING’]. Напишем небольшой пример, чтобы это проиллюстрировать:
<!DOCTYPE html>
<html lang=”ru”>
<head>
<title>Вывод параметров командной строки</title>
<meta charset=’utf-8′>
</head>
<body>
<?php
echo “Данные из командной строки: {$_SERVER[‘QUERY_STRING’]}”;
?>
</body>
</html>

Если теперь мы запустим этот сценарий из браузера (перед этим сохранив его в файле test.php в корневом каталоге сервера) примерно вот таким образом:
http://localhost:4000/qs.php?this+is+the+world
то получим документ следующего содержания:
Данные из командной строки: this+is+the+world
Обратите внимание на то, что URL-декодирование символов не произошло: строка $_SERVER[‘QUERY_STRING’], как и одноименная переменная окружения, всегда приходит в той же самой форме, в какой она была послана браузером. Давайте запомним этот небольшой пример — он еще послужит нам в будущем.

Так как PHP изначально создавался именно как язык для Web-программирования, то он дополнительно проводит некоторую работу с переменной QUERY_STRING перед передачей управления сценарию. А именно, он разбивает ее по пробельным символам (в нашем примере пробелов нет, их заменяют символы +, но эти символы PHP также понимает правильно) и помещает полученные кусочки в массив-список $argv, который впоследствии может быть проанализирован в программе. Заметьте, что здесь действует точно такая же техника, которая принята в C, с точностью до названия массива с аргументами.
Все же массив $argv используется при программировании на PHP крайне редко, что связано с гораздо бóльшими возможностями интерпретатора по разбору данных, поступивших от пользователя. Однако в некоторых (обычно учебных) ситуациях его применение оправдано, так что не будем забывать об этой возможности.

Формы

Вернемся к поставленной задаче. Как нам сделать, чтобы пользователь мог в удобной форме ввести зарегистрированное имя и пароль? Очевидно, придется создать что-нибудь типа диалогового окна Windows, только в браузере. Итак, нам понадобится обычный HTML-документ (например, form.html в корневом каталоге) с элементами этого диалога — текстовыми полями — и кнопкой. Давайте модифицируем форму, которая приводилась раньше, только теперь мы уже будем не просто разбирать, как и куда поступают данные, а напишем сценарий, который эти данные будет обрабатывать Файл form.html:
<!DOCTYPE html>
<html lang=”ru”>
<head>
<title>Cтраница с формой</title>
<meta charset=’utf-8′>
</head>
<body>
<form action=”hello.php”>
Логин: <input type=”text” name=”login” value=””><br />
Пароль: <input type=”password” name=”password” value=””><br />
<input type=”submit” value=”Нажмите кнопку, чтобы запустить сценарий!”>
</form>
</body>
</html>

Загрузим наш документ в браузер. Теперь, если заполнить поля ввода и нажать кнопку, браузер обратится к сценарию hello.php и передаст через ? все атрибуты, расположенные внутри тегов <input> в форме и разделенные символом & в строке параметров. Заметьте, что в атрибуте action тега <form> мы задали относительный путь, т. е. сценарий hello.php будет искаться браузером в том же самом каталоге, что и файл form.html.
Использование форм позволяет в принципе не нагружать пользователя такой информацией, как имя сценария, его параметры и т. д. Он всегда будет иметь дело только с полями, переключателями и кнопками формы.
Осталось теперь лишь определиться, как мы можем извлечь $login и $password из строки параметров. Конечно, мы можем попытаться разобрать ее “вручную” при помощи стандартных функций работы со строками (которых в PHP великое множество), и этот прием действительно будет работать. Однако, прежде чем браться за ненужное дело, давайте посмотрим, что нам предлагает сам язык.

Трансляция полей формы
Итак, мы не хотим заниматься прямым разбором переменной окружения QUERY_STRING, в которой хранятся параметры сценария. И правильно не хотим — интерпретатор перед запуском сценария делает все сам. Причем независимо от того, каким методом — GET или POST — воспользовался браузер. То есть, PHP сам определяет, какой метод был задействован (благо, информация об этом доступна через переменную окружения REQUEST_METHOD), и получает данные либо из QUERY_STRING, либо из стандартного входного потока. Это крайне удобно и достойно подражания, вообще говоря, в любых CGI-сценариях.
Все данные из полей формы PHP помещает в глобальный массив $_REQUEST. В нашем случае значение поля login после начала работы программы будет храниться в $_REQUEST[‘login’], а значение поля password — в $_REQUEST[‘password’]. То есть, не надо ничего ниоткуда “получать” — все уже установлено и распаковано из URL- кодировки. Максимум удобств, минимум затрат, не правда ли? К тому же, еще и работает быстрее, чем аналогичный кустарный код, написанный на PHP, потому что разработчики PHP предусмотрели функцию разбора командной строки на C.
Кроме того, чтобы можно было как-то разделить GET-параметры от POST-данных, PHP также создает массивы $_GET и $_POST, заполняя их соответствующими значениями. Нетрудно догадаться, что $_REQUEST представляет собой всего лишь объединение этих двух массивов.
Наш окончательный сценарий hello.php :

<!DOCTYPE html>
<html lang=”ru”>
<head>
<title>Использование данных формы</title>
<meta charset=’utf-8′>
</head>
<body>
<?php
if ($_REQUEST[‘login’] == “root” && $_REQUEST[‘password’] == “Z10N0101”) {
echo “Доступ открыт для пользователя {$_REQUEST[‘login’]}”;
// Команда блокирования рабочей станции (работает в NT-системах)
system(“rundll32.exe user32.dll,LockWorkStation”);
} else {
echo “Доступ закрыт!”;
}
?>
</body>
</html>

ЗАМЕЧАНИЕ
Да, и на всякий случай проверяйте правильность написания одинарных и двойных кавычек. Возможно несоответствие формата.

Теперь усовершенствуем скрипт — сделаем так, чтобы при запуске без параметров сценарий выдавал документ с формой, а при нажатии кнопки — выводил нужный текст. Самый простой способ определить, был ли сценарий запущен без параметров — проверить, существует ли переменная с именем, совпадающим с именем кнопки от-
правки. Если такая переменная существует, то, очевидно, что пользователь запустил программу, нажав кнопку
// Усовершенствованный скрипт блокировки сервера. Файл lock.php
<!DOCTYPE html>
<html lang=”ru”>
<head>
<title>Усовершенствованный скрипт блокировки сервера</title>
<meta charset=’utf-8′>
</head>
<body>
<?php if (!isset($_REQUEST[‘doGo’])) {?>
<form action=”<?=$_SERVER[‘SCRIPT_NAME’]?>”>
Логин: <input type=”text” name=”login” value=””><br />
Пароль: <input type=”password” name=”password” value=””><br />
<input type=”submit” name=”doGo” value=”Нажмите кнопку!”>
</form>
<?php } else {
if ($_REQUEST[‘login’] == “root” && $_REQUEST[‘password’] == “Z10N0101”) {
echo “Доступ открыт для пользователя {$_REQUEST[‘login’]}”;
// Команда блокирования рабочей станции (работает в NT-системах)  system(“rundll32.exe user32.dll,LockWorkStation”);
} else {
echo “Доступ закрыт!”;
}
} ?>
</html>
</body>

Из этого примера мы можем почерпнуть еще один удобный прием, который нами пока не рассматривался. Это конструкция <?= выражение ?>. Она является не чем иным, как просто более коротким обозначением для <?php echo выражение ?>, и предназначена для того, чтобы вставлять величины прямо в HTML-страницу.

ЗАМЕЧАНИЕ
Помните наши рассуждения о том, что же первично в PHP: текст или программа? Конструкция <?= применяется обычно в тот момент, когда выгодно считать, что первичен текст. В нашем примере именно так и происходит — ведь кода на PHP тут очень мало, в основном страница состоит из HTML-тегов.

Обратите внимание на полезный прием: в параметре action тега <form> мы не задали явно имя файла сценария, а извлекли его из переменной окружения SCRIPT_NAME (которая, как и все такие переменные, хранится в массиве $_SERVER). Это позволило нам не “привязываться” к имени файла, т. е. теперь мы можем его в любой момент переименовать без потери функциональности.
Теперь исчезла необходимость и в промежуточном файле form.html: его код встроен в сам сценарий. Именно так и нужно разрабатывать сценарии: и просто, и делу польза. Здесь действует общий принцип: чем меньше файлов, задающих внешний вид страницы, тем лучше (только не обобщайте это на файлы с программами — последствия могут быть катастрофическими!).

Рассмотрим комплексный пример обработки форм, в которой объединим обработку различных элементов html. Определим следующую форму:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<h2>Анкета</h2>
<form action="input.php" method="POST">
<p>Введите имя:<br>
<input type="text" name="firstname" /></p>
<p>Форма обучения: <br>
<input type="radio" name="eduform" value="очно" />очно <br>
<input type="radio" name="eduform" value="заочно" />заочно </p>
<p>Требуется общежитие:<br>
<input type="checkbox" name="hostel" />Да</p>
<p>Выберите курсы: <br>
<select name="courses[]" size="5" multiple="multiple">
    <option value="ASP.NET">ASP.NET</option>
    <option value="PHP">PHP</option>
    <option value="Ruby">RUBY</option>
    <option value="Python">Python</option>
    <option value="Java">Java</option>
</select></p>
<p>Краткий комментарий: <br>
<textarea name="comment" maxlength="200"></textarea></p>
<input type="submit" value="Выбрать">
</form>

Здесь простейшая стандартная форма ввода анкетных данных:

Обработка сложных форм в PHP

Теперь определим скрипт input.php, который будет обрабатывать эту форму:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php
if(isset($_POST['firstname']) && isset($_POST['eduform']) &&
    isset($_POST['comment']) && isset($_POST['courses']))
{
    $name = htmlentities($_POST['firstname']);
    $eduform = htmlentities($_POST['eduform']);
    $hostel = "нет";
    if(isset($_POST['hostel'])) $hostel = "да";
    $comment = htmlentities($_POST['comment']);
    $courses = $_POST['courses'];
    $output ="
    <html>
    <head>
    <title>Анкетные данные</title>
    </head>
    <body>
    Вас зовут: $name<br />
    Форма обучения: $eduform<br />
    Требуется общежитие: $hostel<br />
    Выбранные курсы:
    <ul>";
    foreach($courses as $item)
        $output.="<li>" . htmlentities($item) . "</li>";
    $output.="</ul></body></html>";
    echo $output;
}
else
{  
    echo "Введенные данные некорректны";
}
?>

Откроем страницу с формой, введем все данные:

Ввод данных в PHP

И отправим форму на сервер:

Залишити відповідь