Продолжаю публиковать полезные (надеюсь) приемы в Ko3.
- Мучаетесь с роутингом? Непонятно, будет ли отрабатывать новый маршрут? Вам в помощь метод
matches($uri)
класса Route. Он принимает на входе тестируемый URI, а возвращает либо FALSE (если адрес не проходит через условия маршрута), либо массив с найденными параметрами (controller, action и прочие). - Есть разница между
$this->request->uri()
и$this->request->route->uri()
. Оба они используют текущий маршрут, но в первом случае по умолчанию будут использованы текущие параметры запроса (контроллер и экшен), а вот во втором — те, что были указаны в методеdefault()
при добавлении маршрута. Таким образом, первый вариант удобен для минимальной корректировки текущего URL (смена id или другого дополнительного аргумента), а второй — для модификации адреса в рамках целого маршрута. - Если в вашем контроллере добавлены методы
before()
иafter()
, не забывайте вызывать в нихparent::before()
иparent::after()
, соответственно в начале и конце метода. Особенно это касается контроллеров-потомков Controller_Template, т.к. в них указанные методы используются для инициализации и вывода основного шаблона$this->template
. - Хотите, чтобы все генерируемые внешние ссылки открывались в новом окне? Используйте свойство
HTML::$windowed_urls
. После установки его значения в TRUE все внешние ссылки (т.е. абсолютные ссылки, с явно указанным протоколом, например HTTP://) будет сгенерированы с атрибутомtarget='_blank'
. Например:
// выводим ссылки на дружественные блоги HTML::$windowed_urls = TRUE; foreach($links as $title => $link) echo HTML::anchor($link, $title)."<br />"; // меняем значение обратно, может пригодиться HTML::$windowed_urls = FALSE;
Замечу, что установка атрибута
target
не очень приветствуется, т.к. поведение таких ссылок непредсказуемо для пользователя. - Очень часто вместо унылых дат вида «15.10.2009″ показывают, сколько времени прошло (так сделано на оф. форуме Kohana, к примеру). Можно вычислять их вручную, а можно использовать «неточный» метод
date::fuzzy_span($timestamp)
. Он смотрит разницу между текущим временем и переданным в$timestamp
(в формате UNIX timestamp, т.к. количество прошедших секунд), и на основании этого выдает фразу типа «меньше суток назад» или «только что». Даже есть поддержка будущего («менее, чем через сутки» или «через пару минут»). Конечно, возвращается строчка на английском, для которой придется делать перевод и выводить результат через__()
. Полный перечень возможных значений можно подсмотреть в исходном коде данного метода (не забудьте, что к строке добавляется префикс ‘in ‘ или суффикс ‘ ago‘, в зависимости от того, наступило событие или еще нет). - Метод
DB::query($type, $sql)
предполагает передачу типа запроса (например ‘select‘) первым параметром. Пусть Вас не смущает наличие константDB::SELECT
,DB::INSERT
,DB::UPDATE
иDB::DELETE
— использовать можно любое значение, даже NULL.
Можно отдельные пост об использовании нового модуля Database в Mysql ?
Мне, как новичку очень пригодиться
Странно, думал, что писал о Database ранее… Посмотрите здесь, если что-то будет непонятно — будем творить
Иван, есть вопрос. Не знаю, большой или нет, но он есть
Начал писать авторизацию на Ko3.
Сделать решил следующим образом:
Создаю Controller_Main extends Controller_Template {}
В конструкторе, вставляю проверку на авторизацию. И по результатам проверки, соответственно нужно сделать одно из двух:
1. вывести форму логина
2. вывести запрошенный контроллер и экшн.
Все остальные контроллеры наследуются от Controller_Main
Но проблема в том, что я не знаю, как прервать поток выполнения, или же подменить вызываемый контроллер и экшн.
Например в __construct() есть код:
if (!$this->a2->logged_in() || $this->user->role !== ‘admin’)
{
echo Request::factory(‘login’)->execute();
}
else
{
// всё окейно. Зашел админ
}
в данном случае форма логина выводится, но — поток выполнения приложения не прерывается, и успешно выводит запрошенный пользователем результат.
Что можно сделать, для решения этой задачи?
1. Вместо конструктора используйте before().
2. Если хочется поменять экшен, просто работайте с Request::$action, он доступен для изменения.
3. Так просто прервать работу фреймворка не получится. Можно бросить Exception, можно сделать редирект (я обычно использую именно его, если надо проводить различные проверки все самого экшена).
>1. Вместо конструктора используйте before().
В этом случае нужно будет в наследуемых классах явно обозначать метод before() ?
before()
{
parent::before();
}
2. редирект использовать не хочу. Ведь в случае ошибки логина будет проблематично передать в запрос информацию о самой ошибке. Опять же — лишние редиректы при проверках мне кажутся недостаточно хорошим решением.
попробую сегодня с before() пошаманить. Спасибо.
1. Да.
2. Ничего проблематичного. Я использую сессии. Кроме того, редирект очищает глобальные массивы $_POST и $_GET, что весьма полезно при работе с формами.
Опять же, что будет с пользователем после того, как он залогинится? Как и куда Вы будете его перенаправлять?
before() спас положение.
В Controller_Main прописал также метод action_login() с отображением формы пользователю и выводом ошибки.
В before() если пользователь не залогинен, и не имеет прав доступа — подменяю action:
Request::instance()->action = ‘login’;
В противном случае — выполнение продолжается по намеченному плану.
Но кстати возник вопрос по обработке ошибок: по умолчанию Kohana останавливается после первой ошибки валидации и возвращает её, не проверяя введенные данные дальше.
Есть какой-то способ, заставить фреймворк проверять все данные формы?
Эм… Если не ошибаюсь, она не останавливается на первой, просто на каждое поле может быть не более одной ошибки. Т.е. если на логине висит несколько правил и ни одно не соблюдено, ошибка сгенерируется только по первому из них.
Если хотите обойти это ограничение, то можете изменить класс Validate, используя каскадную файловую систему Kohana.
да, я ошибся.
Всё работает как надо.