Всем хорошего настроения! Данная статья поможет понять что такое роутер. Сразу скажу: она НЕ рассчитана для новичков, как и большинство материалов данного ресурса. Если вы имеете опыт программирования на PHP и хотите до конца разобраться что же такое роутер и какое отношение он имеет к ЧПУ — эта статья для Вас! Мы с вами создадим элементарнейшую реализацию. В конце статьи выложу исходники для скачивания и тестирования. Потом обсудим недостатки и несколько серьезных готовых решений.
Что же такое роутеры, для чего они нужны, как пользоваться и какой выбрать? Чтобы ответить на эти вопросы, для начала необходимо ознакомиться с понятием «ЧПУ». В этом нам поможет (статья на Wikipedia).
Прочли? Итак, сделали с помощью mod_rewrite и .htaccess «переадресацию» всех несуществующих «файлов» и «папок» на наш index.php. Именно НЕ существующих! Обратите на это особое внимание! И вот теперь нам нужен инструмент, который, собственно говоря, и вызовет нужную функцию или метод (смотря какой подход вы используете при программировании). Можно пойти совершенно банальнейшим способом. Допустим, имеем адрес example.com/catalogue/showitems/10. Приведу пример для ООП, поскольку непоколебимо убежден в тесной связи между ЧПУ и ООП. Это во-первых. Во-вторых: большинство современных фреймворков (Yii, Kohana, CodeIgnitor, CakePHP, Zend и т.д.) используют именно объектно-ориентированный подход, как и большинство готовых роутеров. Так что говорить о процедурке смысла не вижу. Но не будем отвлекаться. Имеем следующее:
http://example.com/catalogue/showitems/10
example.com — домен.
catalogue — класс
showitem — метод
10 — некий параметр, который мы передаем методу.
Создаем папку, например, controllers и пишем в ней файл примерно такого содержания:
//File controllers/catalogue.php class catalogue { public function defaultmethod() { /*Так выводить иноформацию не рекомендуется. Чисто пример. */ echo "Thi is default method of the catalogue class"; } public function showitem($id) { echo "This is showitem method of the catalogue class!"; print_r($id); } } |
Обратите внимание, имя файла должно соответствовать имени класса. Это общепринятый стандарт, не будем вдаваться в подробности — чуть позже из кода поймете почему так нужно. Теперь как нам вызвать метод showitem? Внимательно прочитали статью на википедии? =) Для этого у нас есть .htaccess и mod_rewrite. Наш запрос (http://example.com/catalogue/showitems/10) «переадресовался» на index.php. А там мы можем в простейшем случае сворганить что-то вроде такого парсера/роутера:
//File idex.php $classname = 'defaultclass'; //Имя класса по умолчанию $method = 'defaultmethod'; //Метод по умолчанию $arg = array(); //Массив с аргументами $controllerspath = $_SERVER['DOCUMENT_ROOT'].'/controllers'; //Устаавливаем папку с контроллерами $parsed = parse_url($_SERVER['REQUEST_URI']); //Парсим URL $url = trim(urldecode($parsed['path']), '/'); //Декодируем и убираем лишние слэши. $elements = explode('/', $url); $count = count($elements); if($count > 2) { $classname=$elements[0]; $method=$elements[1]; for($i=2; $i<$count; $i++) { $arg[]=$elements[$i]; } } elseif($count == 2) { $classname=$elements[0]; $method=$elements[1]; } elseif($count == 1 and $elements[0] != NULL) { $classname=$elements[0]; } require_once("$controllerspath/$classname.php"); $obj = new $classname; call_user_func(array($obj, $method), $arg); |
Вот и всё! Какие недостатки? Их, на самом деле, великое множество…
1. Хотим URL вида example.com/article/2 — не получится. Нужен формат «домен/контроллер/метод/id»
2. Конкретно данная реализация упрощена до невозможности и нет обработки исключений. Вызовем не существующий класс и получим ошибку. Тоже самое с методом.
3. Нет маршрутизации по регулярным выражениям. Нет возможности тонкой маршрутизации
4. Не учитывается REST модель.
Ну и хватит, пожалуй. Хотя недостатков, конечно, больше… Но в принце, для каких-то внутренних проектов вполне неплохое решение. Скажем, корпоративный web ресурс для внутреннего использования в сегменте SOHO!
Поэтому теперь, когда мы разобрались что такое URL роутер и можем представить примерно схему его работы, предлагаю посмотреть в сторону AltoRouter. На сегодняшний день мой любимый URL router.