Не хотел бы углублять в конкретную реализацию. Объяснение на уровне абстракций.
C моей точки зрения роутер должен выполнять функцию определения по методу HTTP и строке URI, какая функция должна быть вызвана.
Результатом работы роутера может быть название класса и метода, как в Yii 1. Или может быть даже анонимная функция, как в Laravel, Phalcon, Django, RoR или ExpressJS. Это может быть, наверное, даже ассоциативный массив типа [ "response headers", "response body" ] или имя статического файла.
Как сказал
Сергей Протько, гибкость роутера в том, что роутер ничего не должен знать о логической структуре приложения, но такое я могу сказать только о базовом универсальном роутинге, который работает по карте сопоставлений URI и программных методов. Он действительно мало что знает, потому что парсит регулярки, ищет максимально похожее выражение, возвращает какие-то абстракции.
С моей точки зрения, гибкий роутинг - это такой, который может быть легко заменён на любую альтернативную реализацию. Совместимость обеспечивается использованием объектно-ориентированного подхода с применением интерфейсов или через duck-typing.
Например, роутером может считаться класс, который реализует
RoutingInterface
(это согласно ООП) или содержит метод
route(arguments)
(это duck-typing).
Такой подход позволяет реализовать, например, сопоставление пути вида
myblog/my-article с контролером
"blog/view" через поиск по базе данных, а не по регулярке.
И вот у
Сергей Протько был роутинг с картой сопоставлений, а я заменил на роутинг с использованием базы данных. Логичный вопрос: делать карту сопоставления для всех роутов (что если правил будет больше 100?), либо всё это заносить в базу данных? (всё-всё-всё, каждый путь к профилю всех 100 000 пользователей - они же одинаковые /profile/111222). Ну не гибко же!
Ещё более гибкий роутинг позволяет реализовать каскад роутеров. Если один роутер не смог распознать, кто будет отвечать за этот URI, управление передаётся другому.
Таким образом можно сначала "натравить" на поиск по базе данных, затем по картам соответствий с регулярками.
Или разбить приложение на модули и реализовать роутинг в каждом модуле приложения, а затем соединять их каскадами. Например, пусть за роутинг профиля пользователя отвечает модуль "User", а за записи блога - модуль Blog. Тогда URI вида /profile/111222 возьмёт на себя User, а /profile-as-an-article мог бы бы перехватить блог, и уже если никто не смог, то 404 Page Not found.
Идея гибкого роутинга ясна? Нужны примеры с конкретной реализацией?