В сайтостроении единой точкой входа (в противоположность множественным точкам входа) называется файл-обработчик, принимающий все входящие запросы на программную обработку данных и вывод страниц сайта. Различать запросы исключительно по строке параметров не очень удобно, поэтому совместно с единой точкой входа практически всегда используют ЧПУ.
Первоочередной задачей при создании единой точки входа является реализация перенаправления всех входящих запросов в файл-обработчик, которая осуществляется средствами Web-сервера. Например, в Web-сервере Apache для этой цели можно создать в корневом каталоге сайта файл .htaccess следующего содержания:
RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^.* /index.php
Условие %{REQUEST_FILENAME} !-f
препятствует перенаправлению запросов к существующим файлам в единую точку входа и зацикливанию при обработке правила ^.* /index.php
(обработка правил многопроходная; Web-сервер фиксирует ошибку, когда при выполнении большого количества проходов не появляется признак завершения обработки). В данном примере файлом-обработчиком является index.php, расположенный в корневом каталоге сайта.
Следующей задачей является обработка входящих запросов внутри единой точки входа. Web-сервер предоставляет полный адрес из поступившего запроса, включая строку параметров. Этот адрес доступен внутри единой точки входа в $_SERVER['REQUEST_URI']. Например, можно написать в файле index.php такой код:
<!-- HTML-код --> <pre><?= $_SERVER['REQUEST_URI'] ?></pre> <!-- HTML-код -->
Демонстрация: /gency-demo/single-entry-point?p=1 (в адресной строке вместо single-entry-point можно вписать любые допустимые для пути символы, а вместо 1 – любое натуральное число до 9999999999 включительно).
С полученным адресом можно делать все, что необходимо разработчику. Адрес можно сравнивать с определенными образцовыми адресами или адресными масками, чтобы при совпадении с образцом выполнять закрепленное за этим образцом действие. Адрес можно разделять на части, выделяя компоненты пути и значения параметров, как это сделано в G-Drive/Gency, чтобы уже на основе этих данных выполнять определенное действие.
В качестве примера обработки адреса можно рассмотреть, как в G-Drive/Gency происходит отделение пути от строки параметров1 и выделение компонентов пути2 (фактически выделяются первый компонент пути, т.н. категория, и целиком оставшаяся часть пути, начиная со второго компонента, т.н. объект):
if (strcmp($_SERVER['REQUEST_URI'], $p = strtolower(preg_replace('#//+#', '/', $_SERVER['REQUEST_URI'])))) { header('Location: http'.(empty($_SERVER['HTTPS']) ? '://' : 's://').$_SERVER['HTTP_HOST'].$p, true, 301); exit; } // 1 list($p) = explode('?', $p, 2); // 2 if (count($pa = explode('/', $px = trim($p, '/'), 2)) < 2) $pa[] = '';
Первоначально в переменную $p помещается «нормализованный» адрес без множественных слешей и латинских букв в верхнем регистре, полученный в процессе работы соответствующего фильтра, который допускает дальнейшее выполнение кода только при совпадении значений $_SERVER['REQUEST_URI'] и $p. Затем в переменной $p происходит отделение пути от строки параметров и, таким образом, в ней остается «нормализованный» путь. Далее в переменную $px помещается «нормализованный» путь без первого и последнего слешей. В заключение в массив $pa помещаются выделенные компоненты пути, которые потом можно перенести в отдельные переменные $p0 и $p1:
list($p0, $p1) = $pa;
Демонстрация: /gency-demo-2/single-entry-point?p=1 (в адресной строке вместо single-entry-point можно вписать любые допустимые для пути символы, а вместо 1 – любое натуральное число до 9999999999 включительно).
Спасибо, теперь все понятно!
Если файл-обработчик должен перехватывать все входящие запросы, включая обращения к существующим файлам, в файле .htaccess нужно убрать условие
%{REQUEST_FILENAME} !-f
. Для предотвращения зацикливания в этом случае следует использовать директивуRewriteBase /
совместно с относительным именем файла-обработчика в правиле:Не нужно забывать, что в качестве front-end в связке с Apache может использоваться другой Web-сервер, настроенный таким образом, чтобы обрабатывать обращения к существующим файлам самостоятельно.
Код в статье и фронтальный движок на демосайте обновлены до версии 3.07. Параметр p в адресе теперь может иметь значения до 9999999999 включительно.
Спасибо за такую краткую и информативную статью!
Получается в варианте с RewriteBase все запросы будут проходить через index.php? И тут у меня возник вопрос, а как будут вести себя изображения, файлы стилей и т.п.
Ведь в данном случае возрастает нагрузка: либо отдать статику через прямой запрос, либо все пустить через обработку.
В этом случае либо index.php должен выдавать в том числе и статик, либо нужно размещать статик на другом хосте (за исключением фэйвайкона, роботса и т.п.). И RewriteBase тут играет важную, но не определяющую роль. Эту директиву можно было использовать и в варианте с исключением статика совместно с той же RewriteCond.
Есть ситуации, когда это необходимо, например чтобы отдавать статик только авторизованным пользователям (для оптимизации выдачи статика тут используются специальные методы). Если же такой необходимости нет, вы можете размещать статик на другом хосте, что само по себе является хорошей оптимизацией: не нужно при обработке каждого запроса делать тест на наличие статика.
Такое бывает, например, на сайтах знакомств и т.п., где обычным пользователям представлены только миниатюры, а авторизированным уже полноразмерные изображения – в таком варианте уже логично использовать фронт, но если речь идет об элементах дизайна, то тут нерационально прогонять каждый запрос через фронт.
Согласен. Но и тут возможны исключения. Если это какая-то закрытая панель, то, к примеру, для противодействия «детекту» можно и упомянутый статик закрыть. Или опять-таки подтягивать его с совершенно другого хоста. Также можно использовать комбинированный вариант.