Как сделать единую точку входа с ЧПУ?

В сайтостроении единой точкой входа (в противоположность множественным точкам входа) называется файл-обработчик, принимающий все входящие запросы на программную обработку данных и вывод страниц сайта. Различать запросы исключительно по строке параметров не очень удобно, поэтому совместно с единой точкой входа практически всегда используют ЧПУ.

Первоочередной задачей при создании единой точки входа является реализация перенаправления всех входящих запросов в файл-обработчик, которая осуществляется средствами 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
if (strlen($_SERVER['QUERY_STRING'])) list($p)=explode('?',$p,2);

// 2
if (count($pa=explode('/',$px=trim($p,'/'),2))<2) $pa[]='';

Первоначально в переменную $p помещается «нормализованный» адрес без множественных слешей и латинских букв в верхнем регистре, полученный в процессе работы соответствующего фильтра, который допускает дальнейшее выполнение кода только при совпадении значений $_SERVER['REQUEST_URI'] и $p. Затем в переменной $p происходит отделение пути от строки параметров и, таким образом, в ней остается «нормализованный» путь. Далее в переменную $px помещается «нормализованный» путь без начального и заключительного слешей. В заключение в массив $pa помещаются выделенные компоненты пути.

Демонстрация: /gency-demo-2/single-entry-point?p=1 (в адресной строке вместо single-entry-point можно вписать любые допустимые для пути символы, а вместо 1 – любое натуральное число до 9999999999 включительно).

Комментарии: 4

  1. MrVik

    Спасибо, теперь все понятно!

  2. Михаил

    Если файл-обработчик должен перехватывать все входящие запросы, включая обращения к существующим файлам, в файле .htaccess нужно убрать условие %{REQUEST_FILENAME} !-f. Для предотвращения зацикливания в этом случае следует использовать директиву RewriteBase / совместно с относительным именем файла-обработчика в правиле:

    RewriteEngine On
    
    RewriteBase /
    
    RewriteRule ^.* index.php
    

    Не нужно забывать, что в качестве front-end в связке с Apache может использоваться другой Web-сервер, настроенный таким образом, чтобы обрабатывать обращения к существующим файлам самостоятельно.

  3. Михаил

    Код в статье и фронтальный движок на демосайте обновлены до версии 3.07. Параметр p в адресе теперь может иметь значения до 9999999999 включительно.

  4. Menshakovich

    Спасибо за такую краткую и информативную статью!

Отправить комментарий

Ваш адрес E-mail не будет опубликован.