Object
У прикладі 7.1 демонструється сторінка, яка звертається до користувача з привітанням "Hello". Якщо ця сторінка завантажується у відповідь на передачу форми, то на ній відображається дане вітання. В іншому випадку на сторінці відображається форма, в якій користувач повинен ввести своє ім'я і потім передати форму на обробку
Приклад 7.1. Відображення вітання "Hello" на сторінці
<?php if ('POST' == $_SERVER['REQUEST_METHOD']) { PRINT "Hello, ". $_POST['my_name'];; } else { print<<<_HTML_ <form method="post" action="$_SERVER[PHP_SELF]"> Your name: <input type="text" name="my_name" > <br> <input type="submit" value="Say Hello"> </form> _HTML_; } ?>
Форма, передана на обробку, посилається назад по тому ж URL, з якого був запит, тому що в атрибуті асtion дескриптора <form> вказана спеціальна змінна $_SERVER['РНР_SELF']. Автоглобальний масив $_SERVER містить найрізноманітнішу інформацію про сервер та поточний запит, що оброблюється інтерпретатором РНР, а елемент РНР_SELF масива $_SERVER - шляхову частину URL поточного запиту.
- $_SERVER['REQUEST_METHOD'] - перевіряє елемент чи міститься в ньому метод POST
- GET означає вилучення звичайної сторінки
- POST означає передачу форми
Корисні серверні змінні
Крім змінних РНР_SELF і REQUEST_МEТНОD, автоглобальний масив $_SERVER містить цілий ряд корисних елементів, які надають інформацію про веб-сервер в поточному запиті. Деякі з цих елементів перераховані в табл. 7.1
Таблиця 7.1 . Елементи в масиві $_SERVER
Елемент
Приклад
Опис
QUERY_STRING
category=kitchen&price=5
Частина URL після знака питання, де вказуються параметри URL. У наступному URL демонструється приклад вказівки рядка запиту: http://www.example.com/
catalog/store.php?category=kitchen&price=5
PATH_INFO
/browse
Додаткова інформація про шляхи, що приєднується в кінці URL після знака слеш/. Саме таким способом інформація передається сценарієм, не вдаючись до рядка запиту. У наступному URL демонструється приклад вказівки елемента PATH_INFO: http://www.exaple.com/
catalog/store.php/browse
SERVER_NAME
www.example.com
Найменування веб-сайту, на якому виконується інтерпретатор РНР. Якщо на веб-сервері розміщуються найрізноманітніші домени, та даний елемент містить ім'я окремого віртуального домену, до якого здійснюється доступ
DOCUMENT_ROOT
/usr/local/htdocs
Каталог на комп'ютері веб-сервера, що містить документи, наявні на веб-сайті. Якщо кореневий каталог документів для веб-сайта, доступного за адресою http://www.example.com, знаходиться по шляху /usr/local/htdocs, то запит за адресою http://www.exaple.com/
catalog/store.php відповідає файлу, що знаходиться по шляху /usr/local/htdocs/
catalog/store.php
REMOTE_ADDR
175.56.28.3
IP-адреса користувача, що посилає запит на веб-сервер
REMOTE_HOST
pool0560.cvx.dialup
.verizon.net
Якщо веб-сервер налаштований на перетворення IР-адрес в імена хостів (тобто веб-вузлів), цей елемент містить ім'я хоста користувача, що посилає запит на веб-сервер. А оскільки таке перетворення адреси в ім'я хоста обходиться недешево (з точки зору часу обчислення), то на більшості веб-серверів воно не виконується
HTTP_REFERER1
http://shop.oreilly.com/
product/0636920029335.d
Якщо хто-небудь клацне на посиланні для доступу до сторінки за поточним URL, елемент НТТР_REFERER містить URL сторінки з цим посиланням. Значення цього елемента може бути підроблено, тому не користуйтеся ним як єдиним критерієм для надання доступу до закритих вебсторінок. Проте він може надати допомогу в пошуку тих, хто зв'язується з поточною сторінкою
HTTP_USER_AGENT
Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv: 37.0) Gecko/20100101 Firefox/37.0
Веб-браузер, який видобуває сторінку. У наведеному прикладі показано значення, що позначає сигнатуру браузера Firefox версії 37 для Mac OS Х. Як і значення елемента НТТР_REFERER, значення цього елемента може бути підроблено, хоча воно і корисно для аналізу
1 Правильно пишеться НТТР_REFERRER. Але у первісній специфікації інтернету ім'я цього елемента було зазначено з помилкою, і тому воно часто зустрічається в веб-розробці.
Результат виконання коду в прикладі 7.1
для виконання ввести Your name
Обробка форм за допомогою функцій
Приклад 7.6. Відображення вітання "Hello"на сторінці із застосуванням функцій
Елементарну форму з прикладу 7.1 можна зробити більш гнучкою, перенісши код відображення і обробки в окремі функції. Цей варіант форми з прикладу 7.1 демонструється в прикладі 7.6 із застосуванням функцій. Щоб змінити форму або те, що з нею відбувається коли вона передається на обробку, внесили зміни в тіло функції process_form() або show_form()
<?php //Логіка виконання правильних дій на основі метода запиту if ($_SERVER['REQUEST_METHOD'] == 'POST') { process_form(); } else { show_form(); } //зробити щось, коли форма передана на обробку function process_form() { print "Hello, ". $_POST['my_name']; } //відобразити форму function show_form() { print<<<_HTML_ <form method="post" action="$_SERVER[PHP_SELF]"> Your name: <input type="text" name="my_name" > <br> <input type="submit" value="Say Hello"> </form> _HTML_; } ?>
Результат виконання коду:
Приклад 7.7. Перевірка достовірнотсі даних з форми
<?php //Логіка виконання правильних дій на підставі метода запиту if ($_SERVER['REQUEST_METHOD'] == 'POST') { if (validate_form()) { proccess_form(); } else { show_form(); } } else { show_form(); } //зробити щось, коли формф передана на обробку function proccess_form() { print "Hello, " . $_POST['my_name']; } //відобразити форму function show_form() { print<<<_HTML_ <form method="POST" action="$_SERVER[PHP_SELF]"> Your name: <input type="text" name="my_name"> <br> <input type='submit' value="Say Hello"> </form> _HTML_; } //перевірити дані з форми function validate_form() { //чи має ім'я введене в текстове поле my_name хоча б три символи if (strlen($_POST['my_name']) < 3) { return false; } else { return true; } } ?>
Результат виконання коду:
Your name:
_HTML_;
}
//перевірити дані з форми
function validate_form() {
//чи має ім'я введене в текстове поле my_name хоча б три символи
if (strlen($_POST['my_name']) < 3) {
return false;
} else {
return true;
}
}
*/
?>
<?php //Логіка виконання правильних дій на підставі метода запиту if ($_SERVER['REQUEST_METHOD'] == 'POST') { //Если функция validate_form() возвратит ошибки, передать их функии show_form() if ($form_errors = validate_form()) { show_form($form_errors); } else { proccess_form(); } } else { show_form(); } //зробити щось, коли формф передана на обробку function proccess_form() { print "Hello, " . $_POST['my_name']; } //відобразити форму function show_form($errors = '') { //Якщо передано помилки, вивести їх на екран if ($errors) { print 'Please correct these errors: <ul><li>'; print implode('</li><li>', $errors); print '</li></ul>'; } print<<<_HTML_ <form method="POST" action="$_SERVER[PHP_SELF]"> Your name: <input type="text" name="my_name"> <br> <input type='submit' value="Say Hello"> </form> _HTML_; } //перевірити дані з форми function validate_form() { //Почати з пустого масиву павідомлень про помилки $errors = array(); //додати повідомлення про помилку,якщо введено дуже коротке ім'я if (strlen($_POST['my_name']) < 3) { $errors[] = 'Your name must ge at least 3 letters long.'; } //возвратить ( возможно, пустой) массив сообщений об ошибках return true; } ?>
Результат виконання коду:
Пример 7.9. Проверка достоверности данных в обязательном элементе
<?php if (strlen($_POST['email']) == 0) { $errors[] = "You must enter an email address."; } ?>
Результат виконання коду:
Пример 7.1О. Фильтрация целочисленных входных данных
<?php $ok = filter_input(INPUT_POST, 'age', FILTER_VALIDATE_INT); if (is_null($ok) || ($ok === false)) { $errors[] = 'Please enter a valid age,'; } ?>
Результат виконання коду:
<?php $ok = filter_input(INPUT_POST, 'price', FILTER_VALIDATE_FLOAT); if (is_null ($ok) || ($ok === false)) {$errors[] = 'Please enter а valid price.'; } ?>
Результат виконання коду:
<?php if (strlen(trim($_POST['name'])) == 0) { $errors[] ="Your name is required."; } ?>
Результат виконання коду:
Пример 7.13. Составление массива из преобразованных входных данных
<?php function validate_form() { $errors = array(); $input = array(); $input['age'] = filter_input(INPUT_POST, 'age', FILTER_VALIDATE_INT); if (is_null ($input['age']) || ($input['age'] === false)) { $errors[] = 'Please enter a valid age.'; } $input['price'] = filter_input(INPUT_POST, 'price', FILTER_VALIDATE_FLOAT); if (is_null($input['price']) || ($input['price'] === false)) { $errors[] = 'Please enter a valid price.'; } //воспользоваться нулеобъединяющей операцией, // если значение в элементе $_POST['name']не установлено $input['name'] = trim($_POST['name'] ?? ''); if (strlen($input['name']) == 0) {$errors[] = "Your name is required."; return array($errors, $input); } ?>
Результат виконання коду:
Пример 7. 14. Обработка ошибок и видоизмененных входных данных
<?php //логіка виконання правильних дій на основі метода запиту if ($_SERVER['REQUEST_METHOD'] == 'POST') { //якщо функції validate_form() повертає помилки, передати їх функції show_form() list($form_errors, $input) = validate_form(); if ($form_errors) { show_form($firm_errors); } else { process_form($input); } } else { show_form(); } ?>
Результат виконання коду:
Приклад 7.21. Очищення символьного рядка від дескрипторів НТМ-розмітки strip_tags
//удалить дескрипторы НТМL-разметки из комментариев $comments = strip_tags($_POST ['comments']); // а теперь вывести содержимое переменной $conunents на экран print $comments; //Якщо елемент масиву $_POST['comments'] має наступне: I <b>love</b>sweet<div> class="fancy">rice</div> & tea. при виконанні коду з прикладу 7.21 на экран виводиться наступний результат: I love sweet rice & tea .
Приклад 7.22. Кодування НТМ-уявлень символів в рядку htmlentities
$comment = htmlentities($_POST['comments']); //Якщо елемент масиву $_POST['comments'] має наступне: I <b>love</b>sweet<div class="fancy">rice</div> & tea. спецсимволи змінюються на наступні еквіваленти їх представлень: знак < на НТМL-представление &lt; знак > на НТМL-представление &gt; знак & на НТМL-представление &amp; знак " на НТМL-представление &quot; при виконанні коду з прикладу 7.21 на экран виводиться наступний результат: I <b>love</b>sweet<div class="fancy">rice</div> & tea. Коли браузер виявляє НТМ-уявлення < , Він виводить на екран знак < Замість того, щоб вважати його дескриптором НТМ-розмітки
Збираючи все разом
Приклад закінченої програми щ виконує наступні дії:
- Відображення форми з встановленими за замовчуванням значеннями
- Перевірка достовірності даних, переданих з форми на обробку
- Повторне відображення форми з повідомленнями про помилки і збереженими даними що ввів користувач, якщо передані на обробку дані не достовірні
- Обробка переданих на обробку даних, якщо вони не достовірні
Цей приклад закінченої програми засновано на класі, що має ряд допоміжних методів, щоб спростити відображення і обробку елементів форми що заповнюється.
Приклад 7.29. Допоміжний клас для відоброження та обробки елементів форми що заповнюється
<?php class FormHelper { protected $values = array(); public function __construct($values = array()) { if ($_SERVER['REQUEST_METHOD'] == 'POST') { $this->values = $_POST; } else { $this->values = $values; } } public function input($type, $attributes = array(), $isMultiple = false) { $attributes['type'] = $type; if (($type == 'radio') || ($type == 'checkbox')) { if ($this->isOptionSelected($attributes['name'] ?? null, $attributes['value'] ?? null)) { $attributes['checked'] = true; } } return $this->tag('input', $attributes,$isMultiple); } public function select($options, $attributes = array()) { $multiple = $attributes['multiple'] ?? false; return $this->start('select', $attributes, $multiple) . $this->options($attributes['name'] ?? null, $options) . $this->end('select'); } public function textarea($attributes = array()) { $name = $attributes['name'] ?? null; $value = $this->values[$name] ?? ''; return $this->start('textarea', $attributes) . thmlentities($value) . $this->end('textarea'); } public function tag($tag, $attributes = array(), $isMultiple = false) { return "<$tag {$this->attributes($attributes, $isMultiple)} />"; } public function start($tag, $attributes = array(), $isMultiple = false) { //Дескрипртри <select> і <textarea> //не отримують атрибути value $valueAttribute = (! (($tag == 'select') || ($tag == 'textarea'))); $attrs = $this->attributes($attributes, $isMultiple, $valueAttribute); return "<$tag $attrs>"; } public function end($tag) { return "</$tag>"; } protected function attributes($attributes, $isMutiple, $valueAttribute = true) { $tmp = array(); //Якщо цей дескриптор може містити атрибут value, //а його імені відповідає елемент в масиві значень, //то встановити цей атрибут if ($valueAttribute && isset($attributes['name']) && array_key_exists($attributes['name'], $this->valuse)) { $attributes['value'] = $this->values[$attributes['name']]; } foreach ($attributes as $k => $v) { //Істинне логічне значення означає логічний атрибут if (is_bool($v)) { if ($v) { $tmp[] = $this->encode($k); } } //інакше k = v else { $value = $this->encode($v); //Якщо це багатозначний елемент, //приєднати квадратні дужки ([]) до його імені if ($isMultiple && ($k = 'name')) { $value .= '[]'; } $tmp[] = "$k=\"$value\""; } } return implode(' ', $tmp); } protected function options($name, $options) { $tmp = array(); foreach ($options as $k => $v) { $s = "<option value=\"{$this->encode($k)}\""; if ($this->isOptionSelected($name, $k)) { $s .= ' selected'; } $s .= ">{$this->encode($v)}</option>"; $tmp[] = $s; } return imlplode('', $tmp); } protected function isOptionSelected($name, $value) { //Якщо для аргумента $name в мфсиві відсутній елемент, значить, //цей елемент не можна вибрати if (! isset($this->values[$name])) { return false; } //Якщо ж для аргумента $name в масиві є елемент, який сам є масивом, //перевірити чи є значення аргумента $value в масиві elseif (is_array($this->values[$name])) { return in_array($value, $this0>values[$name]); } //а інакше зрівняти значення аргумента $value з елементом //масиву значень за замовчуванням аргумента $name else { return $value == $this->values[$name]; } } public function encode($s) { return htmlentities($s); } } ?>