# Сессии, Куки, Формы и Шаблонизация Сегодняшнее занятие будет посвящено взаимодействию с пользователем и браузером пользователя. Будут рассмотрены механизмы персонализации сгенерированных PHP страниц, прием данных от пользователя, верстка и шаблонизация. ## Сессии и Куки ### HTTP **HTTP** - протокол, изначально предназначенный для работы в режиме запрос -> ответ, после чего соединение закрывается (вспомним о том, что изначально HTTP - просто средство выдачи страниц для чтения, не более того). **Например** Запрос: ``` GET / HTTP/1.1 Host: example.com Accept: text/html ``` Ответ: ``` HTTP/1.1 200 OK Content-Length: 1983 Content-Type: text/html; charset=utf-8
... ... ``` Таким образом, запрос и ответ состоят из стартовой строки(*GET*), заголовков (*Content-Length*), и собственно контента, ради которого весь этот обмен данных был сделан (html-файл). По окончанию обмена данными соединение разрывается, и следующее обращение к серверу происходит с **чистого листа**. ### Cookie Под сессией подразумевается определенный контекст, в котором происходит обмен данными между клиентом (браузером) и сервером. В этом контексте хранится определенная информация, касающаяся только конкретного клиента (например залогиненного пользователя: логин, пароль, личная переписка и другая персональная информация). Как это работает: - При создании сессии (например, при удачном логине) сервер создает уникальный ключ. Ключ должен быть достаточно большим, что бы его было **крайне** маловероятно подобрать. ``` POST /login/ HTTP/1.1 Host: example.com Accept: text/html login=user&password=eightasterisks ``` - Ключ отсылается в браузер в заголовке вместе с ответом. Браузер запоминает его на определенное время для определенного URL ``` HTTP/1.1 200 OK Content-Type: text/html; charset=utf-8 Set-Cookie: key=LongAndWeirdRandomSecureCharset ... ... ``` Обратите внимание на заголовок **Set-Cookie**. Именно он в себе хранит уникальный ключ, который будет запомнен браузером - Браузер при каждом запросе к серверу отсылает ему этот ключ, подтверждая таким образом, что данное соединение - от конкретного пользователя. ``` GET / HTTP/1.1 Host: example.com Accept: text/html Cookie: key=LongAndWeirdRandomSecureCharset ``` ### PHP Исторически сложилось, что PHP работает так же, как и протокол HTTP - скрипт запускается по запросу, отрабатывает, отдает ответ и *умирает*. Соответственно, **сессия**, как средство сохранения контекста между обращениями к скрипту, организуется в ручном режиме. ```php и взглянув через Developer Tools на заголовки, вы увидите заголовок **Set-Cookie** в ответе сервера. После нажатия **F5**, и в дальнейшем браузер будет посылать заголовок **Cookie** подобного вида: ``` Cookie:PHPSESSID=5q8sgn2j1kj0jk4j5u8rldo5p1 ``` **PHPSESSID** - имя для переменной сессии по умолчанию, можно настроить в php.ini параметром *session.name* #### $_SESSION **Суперглобальный** ассоциативный массив **$_SESSION** является основным хранилищем данных сессии. ```php | | | = $varname ?> | | ### Шаблонно-ориентированные управляющие конструкции Отыскивать парные фигурные скобки не очень удобно в коде с преобладанием **HTML**, поэтому **PHP** имеет не только обычный Си-образный синтаксис для `if`, `while`, `for`, `foreach` и `switch`. В каждом случае основной формой альтернативного синтаксиса является изменение открывающей фигурной скобки на двоеточие (:), а закрывающей скобки на `endif;`, `endwhile;`, `endfor;`, `endforeach;` или `endswitch;` соответственно. ```php A равно 5 ``` Альтернативный синтаксис также применяется и к *else* и *elseif*. Ниже приведена структура *if* с *elseif* и *else* в альтернативном формате: ```php ``` ### MVC Развитие Web-технологий привело к тому, что HTTP отошел от изначальной идеи статических страниц с редкими динамическими вставками и пришел к большим динамическим проектам, в которых HTTP и HTML - не более чем способ реализации клиент-серверной архитектуры и отображения информации пользователю. Одной из основных парадигм, на которой строятся современные Web-приложения, является **MVC** - **Model-View-Controller**. Приложения разделяется на три слоя: - **Model**, слой доступа к СУБД или иному хранилищу данных, и логика работы с хранимыми данными - **View**, слой отображения. Именно эту роль в свое время занимал **PHP** и **SSI**, обычно на этом слое не происходит никаких сложных действий, не содержится бизнес-логики. Данный слой занимается просто вставкой нужных данных в HTML - **Controller**. На этом слое происходит обработка запросов от клиента, обращение к слою **Модели**, и, после получения данных, отправка их во **View** для отображения пользователю. MVC относительно просто в понимании и реализации, что привело к тому, что подавляющее большинство современных Web-фреймворков строится именно на этом принципе. **MVC** мы детально изучим на будущих занятиях; сегодня же мы рассмотрим шаблонизацию в контексте слоя **View** с помощью **PHP** и **Twig** ### Задания #### Задание 1: Форма, сессия, шаблонизация. Сверстать шаблон страниц логина, успешного и неудавшегося входа: 1. Пользователь видит форму с полями ввода логина и пароля; 2. При отправке формы данные сверяются с конфигурацией в ассоциативном массиве; 3. Если логин и пароль верны, то пользователь видит страницу с поздравлением и его логином. Факт успешного логина должен быть отмечен в сессии: 4. Если логин и пароль неверны, пользователь должен получить страницу с ошибкой и его логином. ```php $credentials = array( 'login' => 'foo', 'password' => 'bar'); ``` Выше в ассоциативном массиве находятся поля для проверки. #### Задание 2: Циклическая генерация HTML в шаблоне Добавить к предыдущему заданию следующие возможности: 1. Возможность сделать logout (разлогинится, выйти) 2. При каждом логине запоминать время захода в сессии; 3. Вывести историю заходов в форме таблицы #### Выводы, PHP Hell ## Twig Twig - это обработчик шаблонов, который позволяет отделить *логику* (PHP-код) от *представления* (HTML, CSS, ...), сделанный идентично одному из самых продвинутых шаблонизаторов Jinja. ### Установка ```bash composer require twig/twig:1.* ``` #### Подключение ```php require_once '/path/to/vendor/autoload.php'; $loader = new Twig_Loader_Filesystem('/path/to/templates'); $twig = new Twig_Environment($loader, array( 'cache' => '/path/to/compilation_cache', 'auto_reload' => true, //автоматически перекомпилировать шаблон в кэше )); echo $twig->render('index.tpl', array('url' => 'http://google.com', 'urlText' => 'Гугл')); ``` или ```php require_once '/usr/share/php/Twig/Autoloader.php'; Twig_Autoloader::register(); $loader = new Twig_Loader_Filesystem('templates/'); $twig = new Twig_Environment($loader, array( 'cache' => '/tmp/', 'auto_reload' => true, //автоматически перекомпилировать шаблон в кэше )); echo $twig->render('index.tpl', array('url' => 'http://google.com', 'urlText' => 'Гугл')); ``` ### Переменные Переменные в шаблонах заключаются в двойные фигурные скобки. ```jinja {{ urlText }} ``` Не имеет значения, как обращаться к полям ассоциативных массивов: ```jinja {{ url.title }} ``` Можно обратиться полю с помощью функции attribute: ```jinja {# equivalent to the non-working foo.data-foo #} {# Комментарии заключаются в фигурную скобки и решетки #} {{ attribute(foo, 'data-foo') }} ``` ### Управляющие конструкции Управляющие конструкции заключаются в {% и %}: ```jinja