# Маршруты, URL, и Ссылки В данном разделе будет раскрыты фундаментальные основы маршрутизации запросов Kohana, формирования URL и ссылок. ## маршрутизация Как уже говорилось в секции [порядок выполнения](about.flow), запрос обрабатывается классом [Request], который ищет подходящий маршрут ([Route]) и загружает соответствующий контроллер для выполнения. Таким образом, система обеспечивает большую гибкость, а также интуитивно понятное поведение по умолчанию. Если Вы заглянете в `APPPATH/bootstrap.php`, то увидите следующий участок кода, который будет выполнен непосредственно до передачи запроса в вызов [Request::instance]: Route::set('default', '((/(/)))') ->defaults(array( 'controller' => 'welcome', 'action' => 'index', )); Так устанавливается машрут по умолчанию (`default`) с адресом по шаблону `((/(/)))`. Символы, заключенные в угловые скобки `<>`, являются *ключами*, а круглыми скобками - *необязательные* части адреса. В данном случае весь адрес является опциональным, так что и пустой адрес будет отработан, а дефолтные контроллер и экшен приведут к тому, что для обработки запроса загрузится класс `Controller_Welcome` и выполнится метод `action_index`. Заметьте, что в маршрутах Kohana вне `()<>` допустимы любые символы, а `/` не имеет специального значения. В маршруте по умолчанию `/` используется как разделитель, но пока регулярное выражение имеет смысл, нет никаких ограничений на форматирование Ваших маршрутов. ### Директории Вы можете захотеть разместить некоторые из контроллеров в поддиректориях. Типовое решение для админской части сайта: Route::set('admin', 'admin(/(/(/)))') ->defaults(array( 'directory' => 'admin', 'controller' => 'home', 'action' => 'index', )); Этот маршрут определяет, что адрес должен начинаться с `admin`, в результате значение директории (`admin`) будет взято из дефолтовых значений. Запрос к `admin/users/create` загрузит класс `Controller_Admin_Users` и вызовет метод `action_create`. ### Шаблоны Система маршрутизации Kohana при поиске совпадений использует perl-совместимые регулярные выражения. По умолчанию ключи (окруженные `<>`) определяются шаблоном `[a-zA-Z0-9_]++`, но Вы можете указать свой шаблон для каждого используемого ключа. Для этого заполняется массив ключей и шаблонов, передающийся как дополнительный аргумент метода [Route::set]. Чтобы усложнить предыдущий пример, давайте представим, что у Вас есть админский раздел и секция подразделений (affiliates). Вы можете разделить их по разным маршрутам, а можете объявить как-то так: Route::set('sections', '(/(/(/)))', array( 'directory' => '(admin|affiliate)' )) ->defaults(array( 'controller' => 'home', 'action' => 'index', )); Таким образом мы выделили два раздела сайта, 'admin' и 'affiliate', которые позволят разместить контроллеры по поддиректориям, в остальных случаях будет работать маршрут по умолчанию. ### Еще примеры маршрутов Существует бесчисленное количество возможностей маршрутизации. Вот еще некоторые из них: /* * Короткие адреса для авторизации */ Route::set('auth', '', array( 'action' => '(login|logout)' )) ->defaults(array( 'controller' => 'auth' )); /* * Разноформатные ленты новостей * 452346/comments.rss * 5373.json */ Route::set('feeds', '(/).', array( 'user_id' => '\d+', 'format' => '(rss|atom|json)', )) ->defaults(array( 'controller' => 'feeds', 'action' => 'status', )); /* * Статичные страницы */ Route::set('static', '.html', array( 'path' => '[a-zA-Z0-9_/]+', )) ->defaults(array( 'controller' => 'static', 'action' => 'index', )); /* * Не нравятся слэши? * EditGallery:bahamas * Watch:wakeboarding */ Route::set('gallery', '():', array( 'controller' => '[A-Z][a-z]++', 'action' => '[A-Z][a-z]++', )) ->defaults(array( 'controller' => 'Slideshow', )); /* * Быстрый поиск */ Route::set('search', ':', array('query' => '.*')) ->defaults(array( 'controller' => 'search', 'action' => 'index', )); Маршруты анализируются в том же порядке, в котором были добавлены, так что имейте в виду, что если Вы установили маршрут после загрузки модулей, в одном из загруженных модулей может быть определен маршрут, конфликтующий с Вашим. Поэтому дефолтный маршрут устанавливается последним, так что все пользовательские маршруты будут проверены до него. ### Параметры запроса Директория, контроллер и экшен могут быть доступны через экземпляр класса [Request] одним из двух способов: $this->request->action; Request::instance()->action; Все прочие ключи маршрута могут быть получены из контроллера так: $this->request->param('key_name'); Метод [Request::param] принимает дополнительный параметр, определяющий возвращаемое по умолчанию значение, если оно не было передано в адресе. Если метод вызван без параметром, все ключи будут возвращены в ассоциативном массиве. ### Соглашения Установлено соглашение размещать Ваши маршруты в файле `MODPATH//init.php` модуля, если маршрут относится к данному модулю. Или просто вставить его в файл `APPPATH/bootstrap.php` до дефолтного маршрута, если он относится к приложению в целом. Конечно, они могут быть подгружены из внешнего файла или сгенерированы динамически. ## Адреса URL Помимо мощных возможностей Kohana, есть методы для генерирования URL для Ваших маршрутов. Вы всегда можете определить адрес как строку с помощью [URL::site] для создания URL, примерно так: URL::site('admin/edit/user/'.$user_id); Однако Kohana дает возможность генерировать URL с учетом определенного маршрута. Это очень полезно, если Ваша маршрутизация может поменяться, поскольку это избавит от необходимости заново редактировать весь код, меняя прописанный там адрес. Вот пример динамической генерации, который использует приведенный ранее маршрут `feeds`: Route::get('feeds')->uri(array( 'user_id' => $user_id, 'action' => 'comments', 'format' => 'rss' )); Предположим, Вы решите позже сделать определение маршрута более говорящим, заменив его на `feeds/(/).`. Если Вы будете писать код с генерацией адресов как в примере выше, то не придется менять ни одной строчки кода! Если в адресе есть заключенный в скобки (опциональный) ключ, для которого не передано значение при генерации, и не приведено значение по умолчанию, то данная часть будет исключена из адреса. Примером будет ключ `(/)` дефолтного маршрута; он не будет присутствовать в сгенерированном URL если id не указан. Еще Вы можете часто использовать метод [Request::uri], который по сути делает то же самое, что вышеуказанный метод, только он подставляет текущие значения маршрута, директории, контроллера и экшена. Если текщий маршрут дефолтный, и адрес был `users/list`, для формирования адреса вида `users/view/$id` можно сделать так: $this->request->uri(array('action' => 'view', 'id' => $user_id)); Из шаблона предпочтительнее вызывать: Request::instance()->uri(array('action' => 'view', 'id' => $user_id)); ## Ссылки [!!] Заглушка