Как настроить роутинг php

ЧПУ, роутинг, единая точка входа на PHP

Единая точка входа

Принцип работы единой точки входа очень прост.

Веб-сервер настраивается так, чтобы все HTTP-запросы, вне зависимости от их URL, обрабатывались одним и тем же скриптом index.php .

Текущий URL можно получить из переменной $_SERVER[‘REQUEST_URI’] . Дальше останется только написать свои правила обработки URL-адресов. Упрощённый пример:

Однако в схеме выше есть одно упущение. Ведь если на сервер пришёл запрос к существующему файлу (style.css, script.js, logo.png и т.д) — сервер должен отдать этот файл, а не перенаправлять его.

Вот и весь принцип единой точки входа. Именно так она работает в популярных CMS вроде WordPress и Opencart, в фреймворках Laravel, Symfony и т.д.

Единственный вопрос, который вам останется решить — что делать с запросами к существующим папкам.

Лично я предпочитаю также перенаправлять их на index.php.

На самом деле на сайтах часто используются 2 точки входа.

Первая — index.php, вторая — отдельный скрипт, предназначенный для работы с сайтом через консоль.

Плюсы единой точки входа

  • Позволяет использовать ЧПУ
  • Позволяет полностью управлять URL-адресами в PHP, в том числе хранить URL-адреса в базе данных
  • Скрипты с конфигами, важными функциями и библиотеками подключаются только 1 раз и становятся доступны везде. Не нужно дублировать их подключение где-либо ещё.

Единая точка входа с Apache

Для настройки единой точки входа необходимо добавить несколько строк в конфиг веб-сервера. Проще всего это сделать с помощью файла .htaccess .

Этот файл позволяет переопределять настройки Apache для определённых сайтов и папок.

Добавляем следующие настройки в .htaccess:

Чтобы перенаправление срабатывало для существующих директорий, удаляем строку с !-d в конце, вот так:

Готово. Получить URL адрес текущей страницы можно из переменной $_SERVER[‘REQUEST_URI’] .

Также в интернете часто можно встретить другой вариант конфига, отличается он только последней строкой:

Главное отличие в том, что URL-адрес текущей страницы будет храниться как в $_SERVER[‘REQUEST_URI’] , так и в отдельном GET-параметре, в нашем случае $_GET[‘url_param’] , причём этот URL будет очищен от GET-параметров.

Флаг QSA нужен, поскольку без него GET-параметры не будут работать, т.е. массив $_GET будет содержать только url_param и больше ничего.

Какой из двух вариантов выбрать — решать вам, лично мне больше нравится первый.

Единая точка входа с Nginx

Открываем конфиг домена и внутри секции server прописываем следующее правило:

Простой роутинг

Если единая точка входа настроена правильно, то при заходе по любому несуществующему URL-адресу, например /test должен запуститься файл index.php.

URL текущей страницы находится в переменной $_SERVER[‘REQUEST_URI’]

Теперь мы можем написать очень простой роутер, который смотрит на текущий URL и подключает соответствующий скрипт:

Внесём ещё пару доработок. Во-первых, зачастую URL-адреса должны работать вне зависимости от наличия GET-параметров, поэтому вырежем их из URI:

Читайте также:  E53 не работаю поворотники

Кроме этого, часто требуется получить доступ к определённой части URL. Для этого разобьём URL на части по слешу:

В переменной $segments для URL /products/15 будет лежать массив вида [0 => ‘products’, 1 => ’15’] .

Теперь мы можем легко добавить маршруты для админки:

Это самый простой вариант роутинга. Не идеальный, конечно, но и не требующий знания регулярных выражений (хотя никто не мешает их использовать) и подключения сторонних библиотек.

При хранении URL адресов в базе данных роутинг будет выглядеть примерно так (реальный код зависит от библиотеки, которую вы используете для взаимодействия с БД):

Роутинг средствами htaccess

Какое-то время назад было популярно прописывать правила роутинга прямо в htaccess, вот несколько примеров:

У этого подхода есть несколько недостатков:

  • Плохая читаемость правил
  • Нужно хорошо знать регулярки
  • Хранение правил роутинга в настройках веб-сервера — концептуально не очень хорошая идея

Короче, не используйте этот подход.

Структура URL адресов в админке

Обычно URL адреса в админке формируются по одной из следующих схем:

И сразу рассмотрим простой пример:

Итак, мы видим, что модулем здесь является products , а действием, к примеру, add . Что теперь с этим делать?

Если вы знакомы с ООП и MVC, тогда модулем для вас будет название класса, а действием — метод этого класса, который нужно запустить. Если действие не указано, то принято запускать метод под названием index.

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

Перепишем пример, написанный нами в единой точке входа, под новую схему URL:

Итак, мы берём 1-ый фрагмент URL и проверяем, существует ли в папке pages файл с таким названием.

Т.е. при переходе на страницу /test/test2 скрипт проверит существование файла /pages/test.php . Если файл есть — PHP выполнит этот файл, в противном случае выполнится файл /pages/404.php .

Как видите, при таком подходе нам больше не нужно прописывать соответствие URL-адресов и PHP-файлов. PHP сам будет искать нужный файл в папке pages по первому фрагменту URL.

Теперь осталось только создать файл pages/products.php . Сделаем небольшую заготовку:

Вот так выглядит обработка действий. Мы смотрим на второй фрагмент URL и ищем обработчик этого действия. Для каждого действия (add, update, delete) нужно прописать отдельный блок elseif.

Внутри обработчика add мы смотрим на то, каким методом пришёл запрос, GET или POST. Если GET — отображаем форму, если POST — добавляем товар.

Если вам не нравится вложенная проверка метода, можно сделать иначе. В файле index.php сохраним метод в отдельную переменную:

Затем в products.php меняем заготовку на следующую:

Готово. Да, если вам не нравится, что в коде 2 раза встречается одно и то же действие, только с разными методами, можете использовать немного упрощённую схему URL-адресов из фреймворка Laravel:

Добавление префикса /admin/ в URL

Немного изменим код index.php :

Теперь при запросе страницы /admin/products PHP будет искать файл с названием не products.php , а admin_products.php .

Переименуйте файл и не забудьте заменить в нём все $segments[1] на $segments[2], поскольку в $segments[1] теперь лежит модуль, а в $segments[2] действие.

Читайте также:  Не работает обдув мерседес 124

Продвинутый роутер FastRoute

Если вы ищете более серьёзную систему роутинга, рекомендую изучить библиотеку FastRoute. Это очень мощный роутер, идеально подходящий для сложных приложений, особенно если вы используете ООП.

Если вы хотите, чтобы я написал отдельную статью по работе с FastRoute — пишите об этом в комментариях.

Источник

Простой PHP маршрутизатор

Базовым элементом всех современных PHP фреймворков является роутер, по-другому маршрутизатор (Router), который отвечает за вызов контроллера, соответствующего запрошенному url-адресу. Маршрутизаторы, несмотря на все многообразие реализаций, выполняют одну и туже функцию. Далее мы с вами посмотрим на один из вариантов реализации, который похож на те, которые используются в таких популярных PHP фреймворках как Slim, Silex, Laravel и т.д.

class Router
<
// массив для хранения соответствия url => функция
private static $routes = array();

// запрещаем создание и копирование статического объекта
private function __construct() <>
private function __clone() <>

// данный метод принимает шаблон url-адреса
// как шаблон регулярного выражения и связывает его
// с пользовательской функцией
public static function route($pattern, $callback)
<
// функция str_replace здесь нужна, для экранирования всех прямых слешей
// так как они используются в качестве маркеров регулярного выражения
$pattern = ‘/^’ . str_replace(‘/’, ‘\/’, $pattern) . ‘$/’;
self::$routes[$pattern] = $callback;
>

// данный метод проверяет запрошенный $url(адрес) на
// соответствие адресам, хранящимся в массиве $routes
public static function execute($url)
<
foreach (self::$routes as $pattern => $callback)
<
if (preg_match($pattern, $url, $params)) // сравнение идет через регулярное выражение
<
// соответствие найдено, поэтому удаляем первый элемент из массива $params
// который содержит всю найденную строку
array_shift($params);
return call_user_func_array($callback, array_values($params));
>
>
>
>

Используем следующим образом:

// главная страница вашсайт.рф
Router::route(‘/’, function() <
print ‘Домашняя станица’;
>);

// маршрут будет срабатывать на адрес вашсайт.рф/blog/myrusakov/12091983
// и подобные
Router::route(‘blog/(\w+)/(\d+)’, function($category, $id) <
print $category . ‘:’ . $id;
>);

// запускаем маршрутизатор, передавая ему запрошенный адрес
Router::execute($_SERVER[‘REQUEST_URI’]);

Копирование материалов разрешается только с указанием автора (Михаил Русаков) и индексируемой прямой ссылкой на сайт (http://myrusakov.ru)!

Добавляйтесь ко мне в друзья ВКонтакте: http://vk.com/myrusakov.
Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: http://vk.com/rusakovmy.

Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления

Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.

Порекомендуйте эту статью друзьям:

Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):

Она выглядит вот так:

  • BB-код ссылки для форумов (например, можете поставить её в подписи):
  • Комментарии ( 1 ):

    Расскажите пожалуйста по подробней как происходит вызов контролера действия и самое главное параметров в данном случае

    Для добавления комментариев надо войти в систему.
    Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.

    Copyright © 2010-2021 Русаков Михаил Юрьевич. Все права защищены.

    Источник

    Быстрый роутинг на PHP


    Уходя от использования роутинга в .htaccess файле, в первую очередь пришёл к стандартному направлению на index.php: разбирал там URL и вызывал соответствующие контроллеры — долгое время был доволен такой техникой. Однако совсем недавно осознал, что что-то делаю не так, что можно сделать эффективнее и лучше.
    Далее я расскажу о своём роутинге, использующем XML для хранения правил и в последующем использующем его сериализованный вид.

    Читайте также:  Часы джи шок как настроить дату

    Уходя от проверки в индексном файле, хотел в первую очередь избавиться от подобной конструкции

    Мне не очень хотелось использовать конструкции, предлагаемые большинством фреймворков, в целом выглядящие в таком виде:

    Изначально хотелось хранить правила роутинга в JSON или XML.
    Однако парсить каждый раз файл не очень хорошая идея, и такой тип более пригоден для статической навигации или навигации вида /controller/action/.
    Мне же хотелось большей гибкости в настройке роутинга и в конечном итоге решил использовать XML для хранения правил, а после парсинга файла и создания массива правил сериализовывать его в файл (в дальнейшем используя его для получения настроек)
    XML-файл правил роутинга выглядит примерно так:

    Структура правила представляет собой следующее
    XML-элемент правил содержится в элементе /root/routes, элемент правил должен содержать в себе следующие атрибуты:
    match — Используется для поиска по URL
    controller — Вызываемый контроллер
    action — Вызываемый метод

    match может содержать как статические данные, например «secret», так и динамические «page-», динамические отличаются от статических наличием фигурных скобок и названием переменной в ней (название переменной и её значение будут получены в случае совпадения)
    В переменной можно указать её тип: — выдаст совпадение только в случае, если param1 является числовым значением — выдаст совпадение только в случае, если param2 содержит в себе только буквы и цифры

    На основе XML формируется массив, который разделает статические и динамические правила.
    Все потомки так же разделяются на статических и динамических.
    Так же в элементе /root/system
    хранятся следующие данные:

    Соответственно в случае, если совпадения по правилам роутинга найдены не будут, вернётся 404 ошибка, в случае пустого урл — его index значение

    Источник

    Роутинг PHP и с чем его едят

    Добрый день, Хабраюзеры!
    Сегодня я расскажу вам о роутах и с чем их едят.

    Предисловие

    Пример класса для работы с роутами
    Пример класса с нашими приложениями
    Использование
    Пример запроса

    Запрос к нашему приложению будет выглядеть примерно так: site.com/index.php/modules/test

    Огромное спасибо за внимание!

    О песочнице

    Это «Песочница» — раздел, в который попадают дебютные посты пользователей, желающих стать полноправными участниками сообщества.

    Если у вас есть приглашение, отправьте его автору понравившейся публикации — тогда её смогут прочитать и обсудить все остальные пользователи Хабра.

    Чтобы исключить предвзятость при оценке, все публикации анонимны, псевдонимы показываются случайным образом.

    О модерации

    Не надо пропускать:

    • рекламные и PR-публикации
    • вопросы и просьбы (для них есть Хабр Q&A);
    • вакансии (используйте Хабр Карьеру)
    • статьи, ранее опубликованные на других сайтах;
    • статьи без правильно расставленных знаков препинания, со смайликами, с обилием восклицательных знаков, неоправданным выделением слов и предложений и другим неуместным форматированием текста;
    • жалобы на компании и предоставляемые услуги;
    • низкокачественные переводы;
    • куски программного кода без пояснений;
    • односложные статьи;
    • статьи, слабо относящиеся к или не относящиеся к ней вовсе.

    Источник

    Оцените статью