Home

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 &lt;b&gt;love&lt;/b&gt;sweet&lt;div
    class=&quot;fancy&quot;&gt;rice&lt;/div&gt; &amp; tea.

    Коли браузер виявляє НТМ-уявлення &lt , Він виводить на екран знак
    < Замість того, щоб вважати його дескриптором НТМ-розмітки
  

Збираючи все разом

Приклад закінченої програми щ виконує наступні дії:

  • Відображення форми з встановленими за замовчуванням значеннями
  • Перевірка достовірності даних, переданих з форми на обробку
  • Повторне відображення форми з повідомленнями про помилки і збереженими даними що ввів користувач, якщо передані на обробку дані не достовірні
  • Обробка переданих на обробку даних, якщо вони не достовірні

Цей приклад закінченої програми засновано на класі, що має ряд допоміжних методів, щоб спростити відображення і обробку елементів форми що заповнюється.

Приклад 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);
        }
      }
    ?>