Лекция 2, 2 академических часа. Цель: перейти от архитектуры запроса к исполняемому PHP-коду и безопасной обработке пользовательских данных. Лекция опирается на клиент-серверную модель, HTTP и MVC из лекции 1. Материал готовит к лабораторным работам по настройке PHP, формам и строкам, PDO и аутентификации.
Объясните, что это обзор основы языка в контексте веб-приложения. Синтаксис сразу применяется к форме регистрации, а не изучается отдельно от HTTP.
Свяжите схему с лекцией 1. Откройте исходный код страницы в браузере после первого запуска и покажите, что в нем есть HTML, но нет PHP.
Выполните команды в аудитории. На 1 сентября 2026 года текущая ветка PHP 8.5, но примеры лекции используют стабильные возможности PHP 8.x и не требуют одной конкретной минорной версии.
Укажите две границы: `<?php` открывает блок кода, а `<?=` выводит выражение. `declare(strict_types=1)` должен быть первым оператором файла.
Сравните `$name` и `$Name`. Подчеркните: PHP типизирован динамически, но поддерживает декларации типов на границах функций и классов.
Не перегружайте вводную лекцию полным справочником типов. `enum`, `never`, `void` и составные декларации можно дать для самостоятельного чтения после освоения функций и классов.
Покажите разные результаты strlen и mb_strlen для русского слова. Если mb_strlen недоступна, проверьте расширение командой `php -m`.
На пользовательском вводе предпочитайте строгие сравнения. Не представляйте `==` как всегда ошибочный: у него есть семантика, но неявные преобразования труднее контролировать.
`strict_types` существует с PHP 7.0. Режим задается для файла вызова и влияет на скалярные аргументы и возвращаемые значения; он не превращает PHP в язык со статической типизацией.
Покажите отличие результата функции от `echo`: функция вычисляет строку, а вызывающий код решает, куда ее вывести.
Термины "индексированный" и "ассоциативный" описывают способ использования одного типа `array`, а не два разных типа.
Дайте короткое упражнение: добавить третий товар и изменить предел цены. `array_map` и `array_filter` покажите позже как альтернативу, а не как обязательную замену foreach.
`match` появился в PHP 8.0. Это выражение, а не функция. Оно использует строгое сравнение и без подходящей ветви или `default` выбрасывает `UnhandledMatchError`.
Сопоставьте синтаксическую ошибку, TypeError и исключение предметного правила. Не приучайте подавлять ошибки оператором `@`.
`$_POST['email']` может оказаться строкой, массивом или отсутствовать. Не рекомендуйте `$_REQUEST`: он смешивает источники и скрывает способ передачи данных. JSON читают отдельно из `php://input`.
Измените HTML через DevTools и отправьте форму без required. Так видно, почему клиентские ограничения нельзя считать защитой сервера.
Разделите понятия. Валидация решает, допустимо ли значение. Экранирование делает значение безопасным для конкретного места вывода. Экранированный HTML не следует хранить в базе вместо исходных данных.
Отправьте `email[]=a` через curl или DevTools и покажите, что `is_string` предотвращает предупреждение и случайное преобразование массива в строку.
Введите `"><script>alert(1)</script>` и сравните сырой вывод с `e()`. Атакующую строку не нужно "очищать" перед хранением: правильное кодирование выполняют в месте вывода.
Покажите диалог браузера о повторной отправке формы без PRG. Код 303 явно предписывает перейти к GET после POST.
Откройте Application/Storage в DevTools и покажите cookie сессии. Не демонстрируйте реальные рабочие токены или учетные данные.
На локальном HTTP `cookie_secure=true` помешает отправке cookie, поэтому настройка зависит от HTTPS. Объясните, что срок cookie, серверная очистка и прикладной тайм-аут являются разными механизмами.
Атака использует действующую cookie пользователя, но отправляет запрос с другого сайта. Случайный токен неизвестен атакующему сайту и проверяется на сервере.
Не используйте в учебном шаблоне `root` без пароля. Для лабораторной подготовьте отдельную базу и пользователя с минимально нужными правами.
Сравните с опасной строкой `"... WHERE email = '$email'"`, но не оставляйте ее как шаблон для копирования. Подготовленный запрос предотвращает изменение структуры SQL пользовательским значением.
Не показывайте самодельное хеширование. После успешного входа замените ID сессии; при ошибке логина верните одно и то же сообщение для неизвестного email и неверного пароля.
Попросите студентов найти на схеме границу HTTP, границу базы данных и момент создания аутентифицированной сессии.
`php -l` проверяет синтаксис одного файла, но не заменяет запуск и тестирование. Свяжите каждый этап регистрации с отдельным наблюдаемым результатом.
Вернитесь к сквозному сценарию. Попросите студента назвать функцию или механизм для каждого перехода от POST-запроса к записи пользователя и входу в систему.
Для ответа о strict_types попросите привести пример типизированного параметра. Для массивов ожидайте формулировку "один тип, упорядоченная карта".
Разберите ответы на примере регистрации. Если студент предлагает сохранять результат htmlspecialchars в БД, вернитесь к контексту вывода.
Предложите использовать руководство PHP как справочник по конкретной конструкции. Версию на локальной машине всегда сопоставляют со списком поддерживаемых веток.
Для лабораторной сопоставьте суперглобальные массивы с источниками запроса. Затем используйте рекомендации по сессиям и CSRF как контрольный список.
Для лабораторной сначала откройте страницы о PDO и password_hash. Обратите внимание на примеры обработки ошибок и на то, что алгоритм PASSWORD_DEFAULT может измениться.