• Шаблоны для вашего сайта
  • Сделать сайт
  • Реклама
  • Berry CSS
  • Albireo Framework
  • Бесплатный HTML-курс
  • Telegram-канал
  • Обратная связь
MaxSite.org
О создании сайтов и не только
Создание сайтов под ключ (Украина) →
Вход
×
или зарегистрироваться

PHP-роутинг (Routing) для новичков

PHPПросмотров: 117462Комментарии: 92 февраля 2016 г.

Роутинг — это маршрутизация: входящий URL разбирается специальным образом и по его результату выполняется определенный код. С роутингом напрямую связано понятие ЧПУ (человекопонятные урлы), которое позволяет исключить в адресах сложные параметры. Например вместо http://сайт/admin/new-page пришлось бы использовать http://сайт/admin.php?action=new-page

Любой входящий URL на сервере разбирается по единому стандарту. Полностью приводить документацию не буду (см. как пример функцию parse_url), важно лишь понять, что в адресе передается параметр path (путь на сервере), которого на сервере реально может не быть. Например в адресе http://сайт/admin каталога admin реально может не существовать.

То есть сервер, получив такой адрес, попытается найти каталог admin, но не найдя его, выдаст 404-страницу (not found).

Чтобы исключить такой вариант, серверу указывается, что для всех несуществующих каталогов и файлов, подключать php-файл (обычно index.php).

Делается это в файле .htaccess с помощью Apache-модуля mod_rewrite. Вот довольно типовой вариант (MaxSite CMS):

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L,QSA]

Тут главная строчка с RewriteRule — именно она определяет шаблон входящего адреса (в примере это регулярное выражение) и что с ним делать. В данном примере будет подключен index.php с параметрами после слэша.

Строчка RewriteCond %{REQUEST_FILENAME} !-f / -d указывает исключить из обработки реально существующие на сервере файлы и каталоги.

Похожий вариант, только чуть короче, от WordPress:

RewriteRule . /index.php [L]

Вариант LPF:

RewriteRule ^(.*)$ /index.php?page=$1 [QSA]

Здесь принудительно добавляется query-параметр page.

Еще один распространенный вариант (пожалуй самый «типовой»):

RewriteRule (.*) index.php?$1 [QSA,L]

Все эти RewriteRule-правила делают простую вещь: как бы «преобразуют» входящий адрес в набор query-параметров. Например адрес http://сайт/admin превратится в http://сайт/index.php?admin

Посмотрите на полный код .htaccess:

<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) /index.php?$1 [QSA,L]
</IfModule>

Если это какой-то подкаталог, то он указываетс в RewriteBase и как путь к php-файлу. Например каталог на сервере route:

<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /route/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) /route/index.php?$1 [QSA,L]
</IfModule>

Теперь, все адреса на сервере будут передаваться в файл index.php, а исходный адрес сохранится в виде query-параметра.

Если в index.php разместить

<?php
print_r($_GET);

То мы можем увидеть query-параметры. В PHP за это отвечается суперглобальная переменная $_GET. Например для http://сайт/admin это будет admin, для http://сайт/admin/new-page — admin/new-page.

Таким образом, с помощью .htaccess происходит первая часть роутинга, где мы получаем готовый $_GET.

Кстати, насчет .htaccess WordPress. Он не создает $_GET, поэтому придется использовать $_SERVER['REQUEST_URI'] в который включается подкаталог. Работать с таким адресом уже будет сложней.

Второй этап роутинга выполняется полностью на PHP. Получив $_GET нужно решить что с ним делать. Например если адрес admin, подключить файл admin.php.

Существуют несколько принципиально разных подходов в организации роутинга. Наиболее популярный подход — это когда в адресе передаётся «действие», которое описывается через php-класс. Такой подход хорошо описан в CodeIgniter:

example.com/class/function/id/

Например пусть будет класс admin в нём метод edit, принимающий параметр $id.

example.com/admin/edit/23
 
class admin {
	function edit($id)
	{
		...
	}
}

Это сильно утрированный пример, но он хорошо показывает соответствие адреса и php-класса.

Другой вариант похожий, но используется не классы, а функции.

example.com/admin/edit/23
 
function admin($params)
{
	...
}

То есть функция — это первый сегмент, а остальные выступают уже как парметры. Встречается более «продвинутый» вариант.

example.com/admin
 
function admin($params)
{
	...
}
 
example.com/admin/edit/23
 
function admin_edit($params)
{
	...
}

То есть имя функции строится по сегментам URL.

Третий, тоже распространенный вариант — адрес указывает на подключаемый файл.

example.com/admin
 
$fn = 'pages/admin.php';
 
if (file_exists($fn)) 
	reqiure($fn);
else
	reqiure('pages/404.php');

Здесь все файлы хранятся в каталоге pages и подключаются только если реально существуют. Если файла нет, то подключается предопределенный 404-файл.

Если сайт представляет собой сложный проект, то как правило используют роутинг на основе php-классов. Так его проще поддерживать и развивать. Если же сайт состоит из небольшого количества страниц, то как правило используют подключаемые файлы, где один файл — это одна страница.

Строго говоря, роутинг «на классах» тоже использует «файловое» подключение. Вначале подключается файл с кодом класса, а уже после этого выполняется сам класс.

В задачу роутинга входит не только необходимое «действие», но и валидация входящего адреса и его лексический разбор.

Адреса могут строиться по шаблону. Например какой-то адрес должен содержать только номер, а не текст (например example.com/admin/edit/23, но не example.com/admin/edit/hello). Или адрес может быть неизменным, но обработчик будет меняться от вида запроса GET или POST. В одном случае нужно подключить одну функцию/файл, в другом — другой. Бывают и более сложные задачи, все их перечислять нет смысла, поэтому появились разного рода php-библиотеки для организации роутинга.

Свой «велосипед» не изобретал только ленивый, но я отмечу довольно известный FastRoute, который вобрал в себя наиболее типичные решения.

В первую очередь это использование регулярных выражений при задании правил, например:

$r->addRoute('GET', '/user/{id:[0-9]+}', 'handler1');

Примерно такой же подход используется и в роутинге CodeIgniter.

products/shirts/123
$route['products/([a-z]+)/(d+)'] = "$1/id_$2";

То есть входящий адрес должен соответствовать шаблону и только в этом случае он «сработает».

В FastRoute реализована поддержка POST и GET-запросов. Такая возможность интересна, хотя на больших проектах такие вещи лучше делать на уровне самого «действия». Но это уже тонкости. Про эту библиотеку я упоминаю в первую очередь из-за того, что она достаточно популярна и уже используется в нескольких интересных проектах: Slim и Lumen.

Для небольших проектов, конечно же, FastRoute будет избыточна, поэтому можно ограничиться вариантом попроще, да и мозги потренировать. :-)

ТЗ. Пусть роутинг будет обрабатывать адреса вида http://сайт/blog/contact/map, по которому будет подключен файл content/blog/contact/map/index.php, где каталог content — это общее хранилище всех страниц сайта, а index.php — обязательный файл с кодом страницы. Роутинг должен проверять реальный файл и если его нет, то подключать 404-страницу. Если никаких параметров нет, то это home-страница. Пусть они будут предопределены.

Решение. По сути задача сводится к преобразованию входящего адреса в путь на сервере. У нас есть массив $_GET, где первый ключ и есть входящий URL. Дальше формируем путь к файлу и если он есть, то подключаем. Если нет, то подключаем 404-страницу.

Весь код в 2 строчки:

<?php
 
$fn = ($p = key($_GET)) ? 'content/' . $p . '/index.php' : 'content/home/index.php';
 
(file_exists($fn)) ? require $fn : require 'content/404/index.php'; 
 
# end of file

Это простой роутинг для простых проектов. Достаточно создать в content каталог, как он станет доступен по одноименному адресу.


Создание сайтов (Украина) →
Простое использование SQLite
Почему Яндекс идёт против вебмастеров или как вебмастеру выжить в кризис
twitter.com facebook.com
Другие записи сайта
Сравнение IDE для PHP - 2022
Сравнение IDE для PHP - 2022
Мысли вслух или почему Google лучше Яндекса
Мысли вслух или почему Google лучше Яндекса
Тайм-трекер для учёта времени работы (бесплатно)
Тайм-трекер для учёта времени работы (бесплатно)
База SQLite и основы SQL. Часть 1
База SQLite и основы SQL. Часть 1
Некоторые результаты последнего опроса
Некоторые результаты последнего опроса
Адаптивная сетка. Верстка по-новому
Адаптивная сетка. Верстка по-новому

Комментариев: 9 RSS

1Прогер 8817-01-2019 23:17

Круто, спасибо!

2Александр05-02-2019 10:45

Таки неплохо. Спасибо.

3Богдан08-02-2019 18:12

Объяснение так себе на тройку. В стиле "а вот есть такое, и есть такое", но деталей нет от слова вообще. Понять по этому тексту что куда и зачем можно только если уже знаешь все сам

4Не богдан18-04-2019 19:20

Объяснение так себе на тройку. В стиле "а вот есть такое, и есть такое", но деталей нет от слова вообще. Понять по этому тексту что куда и зачем можно только если уже знаешь все сам

Все четко написано!

А то нашел такую же статью просто выложил код и подписал:

код говорит сам за себя думаю не стоит объяснять!!!

5Аноним31-07-2019 08:31

Очень хороший материал и понятный сначала, но.... зачем в самом низу пример "Весь код в 2 строчки". Это же статья для новичков, понятно что вы крутой программист и можете все упаковать в 2 строки, но зачем усложнять, разложите на простые if(), пусть хоть 10 строк получится, а то ничего в конце не понял

6MAX31-07-2019 09:01

Это сокращенная запись if/else. По идее даже новички их должны знать. Это же базовый синтаксис PHP. :-)

7kubris12-12-2019 14:59

Хорошая основа для новичков под дальнейший PHP обработчик:

//index.php :
$uri = $_SERVER['REQUEST_URI'];

if($uri == '/') {
require 'pages/main.php';
exit;
} else {
echo '404 | ERROR'; //'pages/404.php';
exit;
}

8Alex26-02-2020 11:09

Ну так как реализовать роутинг тот, что в Codeigniter ?

9MAX26-02-2020 15:06

В CodeIgniter (и других фреймворках) два ключевых момента. Первый — шаблон url, на основании которого происходит сравнение текущего адреса. И второй — php-класс, который соответствует этому шаблону. Шаблон url по сути — обычная регулярка, когда она срабатывает, (авто)подключается php-класс с указанным методом.

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

Комментарий будет опубликован после проверки. Вы соглашаетесь с правилами сайта.

(обязательно)

Навигация
  • Шаблоны для MaxSite CMS 22
  • jQuery и JavaScript 6
  • Java и Android 5
  • PHP/ООП 25
  • SQL 17
  • Albireo Framework 11
  • Berry CSS 7
  • CSS, HTML, LESS, SASS 23
  • PHP 37
  • Тайм-менеджмент 9
  • Софт 37
  • SEO 13
  • Git. GitHub 3
  • CodeIgniter 5
  • Landing Page 3
  • Alpine.js 14
  • Фильмы 2
  • Дневник 55

Здесь можно заказать создание сайта (только Украина), шаблона или лендинга. Также вы можете выбрать готовые шаблоны для MaxSite CMS по небольшой цене. Также можно купить отдельные модули, компоненты для вашего сайта.

MaxSite.org
Как создать свой сайт

Услуги по созданию сайтов, блогов, лендингов
Обратная связь • Реклама на сайте
Карта сайта
Мои проекты
  • Шаблоны для вашего сайта
  • Заказать создание сайта
  • MaxSite CMS
  • Berry CSS (CSS Utilities)
  • Albireo Framework
  • UniCSS (Universal Atomic CSS)
  • Landing Page Framework
  • Бесплатные НТML-курсы
Ссылки
  • Telegram-канал
  • Github
  • Twitter
  • Telegram-бот
  • RSS
© MaxSite.org, 2006-2022. Работает на MaxSite CMS | Время: 0.2920 | SQL: 20 | Память: 4.65MB | Вход