В версии 3.2 разработчики поменяли поведение метода Request->uri()
(#3690). В 3.0-3.1 этот метод позволял получить «соседний» URI с применением небольших изменений, например:
// пусть текущий адрес: /articles/page1/ // мы хотим получить ссылку /articles/page2/ $uri = $this->request->uri(array('page' => 2)); |
В 3.2+ этот номер уже не прокатит. Сейчас $this->request->uri()
игнорирует переданные параметры, и возвращает текущий URI. Разработчики предлагают использовать $this->request->route()
, что в принципе логично. Однако есть небольшое НО — этот метод не подставляет текущие параметры объекта Request
, он просто о них не знает. Т.е. нам надо передавать туда все параметры явно, а это очень большая конструкция:
$uri = $this->request->uri( array('page' => 2) + $this->request->param() + array( 'directory' => $this->request->directory(), 'controller' => $this->request->controller(), 'action' => $this->request->action(), ) ); |
Помните, что
$this->request->param()
вернет не все сегменты. Значенияdirectory/controller/action
хранятся в отдельных свойствах и имеют свои методы-геттеры.
Громоздко, ага. Давайте воспользуемся возможностями Каскадной Файловой Системы Kohana и сделаем мир удобнее:
1. Копируем файл SYSPATH/classes/request.php
в APPPATH/classes/
.
2. Добавляем туда новое содержимое метода uri()
:
public function uri(array $params = null) { if ($params === NULL) { return parent::uri(); } $params += $this->_params + array( 'directory' => $this->_directory, 'controller' => $this->_controller, 'action' => $this->_action, ); return $this->_route->uri($params); } |
Вуаля! Теперь можно использовать $this->request->uri()
как для получения текущего URI, так и для быстрого reverse-routing на базе текущих параметров:
$uri = $this->request->uri(); // текущий адрес $uri = $this->request->uri(array('action' => 'test')); // меняем в URI текущий экшен на action_test() |
Обратите внимание, что новый метод
uri()
применяет ВСЕ текущие значения объектаRequest
. Таким образом, если мы меняем только экшен, то все остальные параметры останутся прежними, в том числе и те, которые в роуте шли после экшена. Например, при текущем адресе foo/bar/123, вызов$this->request->uri(array('action' => 'baz'))
вернет строку ‘foo/baz/123‘, а не ‘foo/baz‘.
Содержимое файла request.php
выложил на гитхаб: https://gist.github.com/2773591.
дада, помнится мне я нехило получил проблем, когда обновился до 3.2 — тогда то и родилась поделка, которая это реализовывала — правда в виде отдельного класса и ряда статических методов.
Я думаю, следовало бы упомянуть еще тот факт, что именно uri лучше всего использовать с хелперами HTML, Form. А то народ путает (или не знает) и получает непонятные вещи при переносе приложения в подпапку DOCUMENT_ROOT-а.
Думаю, многим было бы интересно поглядеть эту «поделку». Есть возможность ее выложить?
вот тут можно глянуть. Действовал по принципу дешево и сердито, теперь же хочу перенести данную логику в класс Request..
Да, супер, что тут сказать… Меня самого очень обломало это «усовершенствование». Т.е. разработчики убрали из ядра такую полезную возможность, а мы теперь должны в каждом своём проекте дописывать это обрано. Отлично!
И ещё мне очень не нравится, что они никак не хотят исправлять очевидные баги, сообщения о которых висят уже по году и более. Например, некорректное кодирование символов в функции URL::site() и Route::url()
@Spider
Мы уже обсуждали исправления багов в комментах к одной из предыдущих статей. Мое мнение такое — если тикет переведен в unsheduled, то надо периодически этот тикет АПить. Ну или отправить Pull Request — это сильно ускоряет работу над тикетом. Есть ощущение, что в последнее время у разработчиков не слишком много свободного времени для разработки.
Согласен, пулл реквесты надо делать, Kohana всё-таки позиционируется как community-driven framework