Создание URL-ссылок
Создавать ссылки в Nette так же просто, как тыкать пальцем. Просто наведите курсор, и система сделает всю работу за вас. Мы покажем:
- как создавать ссылки в шаблонах и других местах
- как выделить ссылку на текущую страницу
- что делать с недействительными ссылками
Благодаря двунаправленной маршрутизации, вам никогда не придется жестко кодировать URL приложения в шаблонах или коде, которые могут измениться позже или быть сложными для составления. Просто укажите презентера и действие в ссылке, передайте любые параметры, и фреймворк сам сгенерирует URL. Фактически, это очень похоже на вызов функции. Вам понравится.
В шаблоне презентера
Чаще всего мы создаем ссылки в шаблонах, и отличным помощником
является атрибут n:href
:
<a n:href="Product:show">подробнее</a>
Обратите внимание, что вместо HTML-атрибута href
мы использовали n:attribute n:href
. Его значением
является не URL, как вы привыкли видеть в атрибуте href
, а имя
презентера и действие.
Нажатие на ссылку, проще говоря, является чем-то вроде вызова метода
ProductPresenter::renderShow()
. И если в его сигнатуре есть параметры, мы можем
вызвать его с аргументами:
<a n:href="Product:show $product->id, $product->slug">подробнее</a>
Также можно передавать именованные параметры. Следующая ссылка
передает параметр lang
со значением en
:
<a n:href="Product:show $product->id, lang: en">подробнее</a>
Если метод ProductPresenter::renderShow()
не имеет в своей сигнатуре
$lang
, то он может получить значение параметра с помощью
$lang = $this->getParameter('lang')
или из свойства.
Если параметры хранятся в массиве, их можно расширить с помощью
оператора (expand)
(что-то вроде оператора ...
в PHP, но работает
с ассоциативными массивами):
{var $args = [$product->id, lang => en]}
<a n:href="Product:show (expand) $args">подробнее</a>
Так называемые постоянные параметры также автоматически передаются в ссылках.
Атрибут n:href
очень удобен для HTML-тегов <a>
. Если мы
хотим вывести ссылку в другом месте, например, в тексте, мы используем
{link}
:
URL: {link Home:default}
В коде
Метод link()
используется для создания ссылки в презентере:
$url = $this->link('Product:show', $product->id);
Параметры также могут быть переданы в виде массива, в котором также могут быть указаны именованные параметры:
$url = $this->link('Product:show', [$product->id, 'lang' => 'cs']);
Ссылки можно создавать и без презентера, используя LinkGenerator и его метод link()
.
Ссылки на презентер
Если целью ссылки является презентер и действие, она имеет такой синтаксис:
[//] [[[[:]module:]presenter:]action | this] [#fragment]
Формат поддерживается всеми тегами Latte и всеми методами презентера,
которые работают со ссылками, т. е. n:href
, {link}
, {plink}
,
link()
, lazyLink()
, isLinkCurrent()
, redirect()
,
redirectPermanent()
, forward()
, canonicalize()
, а также LinkGenerator. Поэтому, даже если в примерах используется
n:href
, здесь может быть любая из функций.
Поэтому основной формой является Presenter:action
:
<a n:href="Home:default">главная страница</a>
Если мы ссылаемся на действие текущего презентера, мы можем опустить его имя:
<a n:href="default">главная страница</a>
Если действие является default
, мы можем опустить его, но
двоеточие должно остаться:
<a n:href="Home:">главная страница</a>
Ссылки могут также указывать на другие модули. Здесь
ссылки различаются на относительные по отношению к подмодулям или
абсолютные. Принцип аналогичен дисковым путям, только вместо косых
черт стоят двоеточия. Предположим, что настоящий презентер является
частью модуля Front
, тогда мы напишем:
<a n:href="Shop:Product:show">ссылка на Front:Shop:Product:show</a>
<a n:href=":Admin:Product:show">ссылка на Admin:Product:show</a>
Особым случаем является ссылка на себя. Здесь
мы напишем this
в качестве цели.
<a n:href="this">refresh</a>
Мы можем ссылаться на определенную часть HTML-страницы через так
называемый фрагмент после хэш-символа #
:
<a n:href="Home:#main">ссылка на Home:default и фрагмент #main</a>
Абсолютные пути
Ссылки, генерируемые link()
или n:href
, всегда являются
абсолютными путями (т.е. начинаются с /
), но не абсолютными URL с
протоколом и доменом, как https://domain
.
Чтобы создать абсолютный URL, добавьте две косые черты в начало
(например, n:href="//Home:"
). Или вы можете переключить презентатор на
генерацию только абсолютных ссылок, установив
$this->absoluteUrls = true
.
Ссылка на текущую страницу
Цель this
создаст ссылку на текущую страницу:
<a n:href="this">обновить</a>
В то же время все параметры, указанные в сигнатуре action<Action>()
или render<View>()
метода, если action<Action>()
не определены,
передаются. Таким образом, если мы находимся на страницах
Product:show
и id:123
, то ссылка на this
также будет
передавать этот параметр.
Конечно, можно указать параметры напрямую:
<a n:href="this refresh: 1">обновить</a>
Метод презентера isLinkCurrent()
определяет, совпадает ли цель
ссылки с текущей страницей. Это можно использовать, например, в шаблоне
для разграничения ссылок и т. д.
Параметры те же, что и для метода link()
, но также можно
использовать подстановочный знак *
вместо конкретного
действия, что означает любое действие презентера.
{if !$presenter->isLinkCurrent('Admin:login')}
<a n:href="Admin:login">Войти</a>
{/if}
<li n:class="$presenter->isLinkCurrent('Product:*') ? active">
<a n:href="Product:">...</a>
</li>
Сокращенная форма может использоваться в сочетании с n:href
в
одном элементе:
<a n:class="$presenter->isLinkCurrent() ? active" n:href="Product:detail">...</a>
Символ подстановки *
заменяет только действие презентера, но
не сам презентер.
Чтобы узнать, находимся ли мы в определенном модуле или его
подмодуле, мы можем использовать метод
$presenter->isModuleCurrent(moduleName)
.
<li n:class="$presenter->isModuleCurrent('MyEshop:Users') ? active">
<a n:href="Product:">...</a>
</li>
Ссылки на сигнал
Целью ссылки может быть не только презентер и действие, но и сигнал (они вызывают метод handle<Signal>()
).
Синтаксис следующий:
[//] [sub-component:]signal! [#fragment]
Поэтому сигнал выделяется восклицательным знаком:
<a n:href="click!">signal</a>
Вы также можете создать ссылку на сигнал подкомпонента (или подсубкомпонента):
<a n:href="componentName:click!">signal</a>
Ссылки на компонент
Поскольку компоненты — это отдельные многократно
используемые единицы, которые не должны иметь никаких отношений с
окружающими презентерами, ссылки работают немного по-другому. Атрибут
Latte n:href
и тег {link}
, а также методы компонентов, такие как
link()
и другие, всегда рассматривают цель как имя сигнала.
Поэтому нет необходимости использовать восклицательный знак:
<a n:href="click">сигнал, не действие</a>
Если мы хотим сделать ссылку на презентеры в шаблоне компонента, мы
используем тег {plink}
:
<a href={plink Home:default}>главная страница</a>
or in the code
$this->getPresenter()->link('Home:default')
Псевдонимы
Иногда полезно назначить легко запоминающийся псевдоним для пары
Ведущий:действие. Например, вы можете назвать домашнюю страницу
Front:Home:default
просто home
или Admin:Dashboard:default
–
admin
.
Псевдонимы задаются в конфигурации под ключом
application › aliases
:
application:
aliases:
home: Front:Home:default
admin: Admin:Dashboard:default
sign: Front:Sign:in
В ссылках они записываются с использованием символа at, например:
<a n:href="@admin">administration</a>
Они поддерживаются во всех методах, работающих со ссылками, таких как
redirect()
и подобные.
Недействительные ссылки
Может случиться так, что мы создадим некорректную ссылку — либо
потому, что она ссылается на несуществующий презентер, либо потому, что
она передает больше параметров, чем целевой метод получает в своей
сигнатуре, либо когда не может быть сгенерирован URL для целевого
действия. Что делать с недействительными ссылками, определяется
статической переменной Presenter::$invalidLinkMode
. Она может иметь одно из
этих значений (констант):
Presenter::InvalidLinkSilent
— тихий режим, возвращает символ#
в качестве URL-адресаPresenter::InvalidLinkWarning
— будет выдано сообщение E_USER_WARNINGPresenter::InvalidLinkTextual
— визуальное предупреждение, текст ошибки отображается в ссылкеPresenter::InvalidLinkException
— будет выброшено исключение InvalidLinkException
По умолчанию в рабочем режиме используется параметр
InvalidLinkWarning
, а в режиме разработки —
InvalidLinkWarning | InvalidLinkTextual
. InvalidLinkWarning
не убивает сценарий в
рабочей среде, но предупреждение будет зарегистрировано в журнале. В
среде разработки Tracy перехватит предупреждение
и отобразит синюю страницу ошибки. Если установлен InvalidLinkTextual
,
презентер и компоненты возвращают сообщение об ошибке в виде URL-адреса,
который отмечен #error:
. Чтобы сделать такие ссылки видимыми, мы
можем добавить правило CSS в нашу таблицу стилей:
a[href^="#error:"] {
background: red;
color: white;
}
Если мы не хотим, чтобы предупреждения создавались в среде разработки, мы можем включить режим автоматической недопустимой связи в конфигурации.
application:
silentLinks: true
LinkGenerator
Как создавать ссылки с таким же комфортом, как с методом link()
,
но без презентера? Для этого у нас есть Nette\Application\LinkGenerator.
LinkGenerator — это сервис, который можно передать через конструктор, а затем создать ссылки с помощью метода ‚link()‘.
Есть разница по сравнению с презентерами. LinkGenerator создает все ссылки как абсолютные URL-адреса. Кроме того, нет «текущего презентера», поэтому невозможно указать только имя действия ‚link('default‘)' или относительные пути к модулям.
Недопустимые ссылки всегда выбросывают исключение
Nette\Application\UI\InvalidLinkException
.