Хороший пример реализации роутинга/чпу?

Не буду вдаваться в историю проекта. Скажу, что сейчас подходит этап, когда у программистов появится время, на частичное переписывание старого и страшного кода. Приоритетной считаю систему ЧПУ. Работает она примерно так:

— Класс ЧПУ, делает explode URL по слэшам(потом появился костыль, приравнивающий "_" к "/").

— Первый элемент массива — имя модуля. Огромный свитч, который находит и передает управление модулю.

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


Система в принципе работает, раньше было ещё хуже и даже нужный метод модуля в основном классе ЧПУ вызывался, следствием чего, часто было, что какие-либо функции отпадали при переписывание. Но проблема даже не в этом, а в том, что возникают не удобства с параметрам в URL. Если например /news/1740/page/2

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


Прошу совета и праведного пинка.

Фреймворки с хорошей и гибкой системой роутинга, недавно видел у Kohana, заинтересовался. Прикручивать целый фреймворк скорее всего не будем. Интересен ваш опыт, советы, может быть нюансы на которые лучше посмотреть. Примеры из других фреймворков, сейчас хороших много, а каждый изучать времени нет.

Проект на PHP.


Спасибо за внимание и потраченное на меня время.
Надеюсь задал вопрос и описал проблему понятно. Будут уточнения — вперед. Плюсами одарю:)
  • Вопрос задан
  • 10264 просмотра
Пригласить эксперта
Ответы на вопрос 5
Fesor
@Fesor
Full-stack developer (Symfony, Angular)
symfony.com/doc/current/book/routing.html — ознакомьтесь, возможно вам будет любопытно.

В любом случае, делать жесткую структуру ссылок нерентабельно. Лучше описывать правила маршрутизации хотя бы как в Yii (просто паттерны регулярных выражений).
Ответ написан
MpaK999
@MpaK999
Буду!
Посмотрите как реализован роутинг в Ruby on Rails, ничто не мешает реализовать подобное же на PHP
Ответ написан
@Big_Shark
Посмотрите как сделано в CMF laravel.com/docs/routing, очень гибкая и удобная структура получается.
Ответ написан
Комментировать
FanKiLL
@FanKiLL
У меня правда для java.
routes = new ArrayList<RouteData>();
routes.add(new RouteData("GET", "home/index/{^[0-9]{1,15}$}/valid/{^[A-z]{3,15}$}"));
routes.add(new RouteData("POST", "home/index/{^[0-9]{1,15}$}/valid/{^[A-z]{3,15}$}"));


Я в своё время решил параметры держать в {} скобках, так парсер знает что это параметр + можно регулярку туда засунуть, чтоб роутинг чётко совпадал. Плюс держа в скобках, вы можете делать роутинг не по паттерну Controller/Action/id А что-нибуть более гибкое(особенно с регулярками описывающие парраметр)

Controller/Action/{id}
Controller/{id}/Action
Controller/Action/{name}/delete/{id}


Плюс в моём примере метод запроса (POST, GET DELETE...) тоже имеет значение.
Парсер роутера, разбирает пришедший запрос и ищет есть ли такой роутинг у нас, при первом же совпадение, например
Question/Read/{name}/{id} + метод запроса тоже должен совпадать.

Запустится Controller = Question, Action = Read с параметрами name, id

Конечно с помощью reflection проверяется есть ли такой контроллер и action метод с такими параметрами если нет — 404

Вообщем как то так, трудно описать, если что спрашивайте. Но думаю принцип понятен.

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

Http Method Delete: User/Profile/{name}/delete/{id} параметр delete в url не играет никакой роли, он просто для удобства и понимания что делает URL.
Ответ написан
Комментировать
@tarya
Я в своей cms сделал достаточно просто и работает как часы.

Все примерно так:

При инициализации страницы дергается метод parseBaseURL() в нем вычленяются из $_SERVER[«REQUEST_URI»] базовые переменные. А базовые для движка такие /ru/section/document.html

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

Далее. Вот пример: посетитель зашел по урлу /news/ — это у нас раздел сайта. В нем дергается модуль. Все что будет далее строиться например /news/page-1/, /news/view-1/, /news/download/file.zip или как угодно и что угодно может быть в урле. Как я это все распознаю. Базовый разбор был еще при инициализации, далее как я сказал дергается раздел, а к нему прицеплен модуль. В модуле я могу задать любой шаблон для урла.

Например:

$u_goods->addURL("#/cat-(\d+)/?#i", «category»);//add cat
$u_goods->addURL("#/goods-(\d+)/?#i", «goods»);//add goods
$u_goods->addURL("#/page-(\d+)/?$#i", «p»);//add pages var

И все. Уже в классе становятся доступные переменные category, goods, p. И так далее.

Итого — урл может быть какой угодно, и всегда в модуле для любого угла можно задать свое правило.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы