Пока мы проверяли путь прямо в index.php и выводили заголовок там же. Когда появятся список, форма, обработчик и страница книги, один файл станет трудно читать. Разделим приложение на маршрутизатор и шаблоны, оставив одну публичную точку входа.
Публичная папка — единственная точка входа
Веб-сервер должен отдавать файлы только из public/. Классы, JSON-каталог, настройки и зависимости Composer хранятся рядом или выше, но не по публичному URL. Это простая граница: браузеру доступны только файлы и ответы, которые приложение решило показать.
Распознаём два маршрута
Для небольшого приложения можно начать с проверки пары метод/путь. В public/index.php:
<?php
declare(strict_types=1);
require dirname(__DIR__) . '/vendor/autoload.php';
$method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
$path = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH) ?? '/';
if ($method === 'GET' && $path === '/books') {
$books = [];
require dirname(__DIR__) . '/templates/books.php';
exit;
}
http_response_code(404);
require dirname(__DIR__) . '/templates/404.php';
Имя шаблона в коде фиксировано. Не используйте ввод из URL как часть пути для require: адрес вида ?page=... не должен выбирать произвольный файл на сервере.
Экранируйте текст в шаблоне
Создайте templates/books.php. Функция e() экранирует обычный текст для HTML-контекста:
<?php
function e(string $value): string
{
return htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}
?>
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<title>Мои книги</title>
</head>
<body>
<h1>Мои книги</h1>
<ul>
<?php foreach ($books as $book) : ?>
<li><?php echo e($book->title); ?></li>
<?php endforeach; ?>
</ul>
</body>
</html>
Если название содержит строку <script>, браузер покажет её текстом, а не выполнит как разметку. Экранируйте при выводе, потому что безопасная строка зависит от контекста: текст, атрибут, URL и JavaScript требуют разных правил.
Шаблон не должен загружать данные
Маршрут подготовил переменную $books, а шаблон отвечает за HTML. Если шаблон сам читает файл или выполняет SQL-запрос, отображение и хранение снова смешаются. Разделение помогает понять, где искать ошибку: данные не пришли или разметка вывела их неверно.
Добавляем 404-шаблон
В templates/404.php выведите простую страницу и оставьте ранее заданный статус 404. Не вставляйте туда переданные URL-фрагменты как HTML. Если показываете запрошенный путь, передайте его через e().
Проверьте /books, неизвестный маршрут и название книги со специальными символами. Теперь форма сможет отправить данные по отдельному POST-маршруту; в следующей части добавим проверку и защиту от поддельной отправки.
Навигация по курсу
Часть 12 из 16.
← Часть 11: HTTP на PHP: разбираем запрос и формируем ответ · Часть 13: PHP-формы POST: проверка данных и защита CSRF →
0
10