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);
}
}
?>