Създаване на URL връзки
Създаването на връзки в Nette е лесно като посочване с пръст. Достатъчно е само да насочите и фреймуъркът вече ще свърши цялата работа вместо вас. Ще покажем:
- как да създаваме връзки в шаблони и другаде
- как да различим връзка към текущата страница
- какво да правим с невалидни връзки
Благодарение на двупосочното маршрутизиране никога няма да се налага да записвате твърдо URL адреси на вашето приложение в шаблони или код, които могат по-късно да се променят, или сложно да ги сглобявате. Във връзката е достатъчно да посочите презентера и действието, да предадете евентуални параметри и фреймуъркът вече ще генерира URL сам. Всъщност е много подобно на извикването на функция. Това ще ви хареса.
В шаблона на презентера
Най-често създаваме връзки в шаблони и страхотен помощник е
атрибутът n:href
:
<a n:href="Product:show">детайл</a>
Забележете, че вместо HTML атрибута href
използвахме n:атрибут n:href
. Неговата
стойност тогава не е URL, както би било в случая с атрибута href
, а
името на презентера и действието.
Кликването върху връзка е, опростено казано, нещо като извикване на
метода ProductPresenter::renderShow()
. И ако той има параметри в своята
сигнатура, можем да го извикаме с аргументи:
<a n:href="Product:show $product->id, $product->slug">детайл на продукта</a>
Възможно е да се предават и именувани параметри. Следващата връзка
предава параметъра lang
със стойност cs
:
<a n:href="Product:show $product->id, lang: cs">детайл на продукта</a>
Ако методът ProductPresenter::renderShow()
няма $lang
в своята
сигнатура, може да разбере стойността на параметъра с помощта на
$lang = $this->getParameter('lang')
или от свойство.
Ако параметрите са съхранени в масив, могат да се разгърнат с
оператора ...
(в Latte 2.x с оператора (expand)
):
{var $args = [$product->id, lang => cs]}
<a n:href="Product:show ...$args">детайл на продукта</a>
Във връзките автоматично се предават и т.нар. персистентни параметри.
Атрибутът n:href
е много удобен за HTML тагове <a>
. Ако
искаме да изпишем връзка другаде, например в текст, използваме
{link}
:
Адресът е: {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">обнови</a>
Можем да свързваме към определена част от страницата чрез т.нар.
фрагмент след знака диез #
:
<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 !isLinkCurrent('Admin:login')}
<a n:href="Admin:login">Влезте</a>
{/if}
<li n:class="isLinkCurrent('Product:*') ? active">
<a n:href="Product:">...</a>
</li>
В комбинация с n:href
в един елемент може да се използва
съкратена форма:
<a n:class="isLinkCurrent() ? active" n:href="Home:">...</a>
Заместващият знак *
може да се използва само вместо действие, а
не презентер.
За да проверим дали сме в определен модул или негов подмодул,
използваме метода isModuleCurrent(moduleName)
.
<li n:class="isModuleCurrent('Forum:Users') ? active">
<a n:href="Product:">...</a>
</li>
Връзки към сигнал
Целта на връзката не трябва да бъде само презентер и действие, но и сигнал (извикват метода
handle<Signal>()
). Тогава синтаксисът е следният:
[//] [sub-component:]signal! [#fragment]
Сигналът следователно се отличава с удивителен знак:
<a n:href="click!">сигнал</a>
Може да се създаде и връзка към сигнал на подкомпонент (или под-подкомпонент):
<a n:href="componentName:click!">сигнал</a>
Връзки в компонент
Тъй като компонентите са
самостоятелни цялости за многократна употреба, които не трябва да имат
никакви връзки с околните презентери, връзките тук работят малко
по-различно. Атрибутът на Latte n:href
и тагът {link}
и методите
на компонента като link()
и други считат целта на връзката винаги
за име на сигнал. Затова не е необходимо дори да се посочва
удивителен знак:
<a n:href="click">сигнал, а не действие</a>
Ако искаме в шаблона на компонента да свързваме към презентери, ще
използваме за това тага {plink}
:
<a href={plink Home:default}>начало</a>
или в кода
$this->getPresenter()->link('Home:default')
Псевдоними
Понякога може да е полезно да се присвои на двойката Presenter:действие
лесно запомнящ се псевдоним. Например началната страница
Front:Home:default
да се нарече просто home
или Admin:Dashboard:default
като admin
.
Псевдонимите се дефинират в конфигурацията под ключа
application › aliases
:
application:
aliases:
home: Front:Home:default
admin: Admin:Dashboard:default
sign: Front:Sign:in
Във връзките след това се записват с помощта на знак @, например:
<a n:href="@admin">администрация</a>
Поддържат се и във всички методи, работещи с връзки, като redirect()
и подобни.
Невалидни връзки
Може да се случи да създадем невалидна връзка – или защото води към
несъществуващ презентер, или защото предава повече параметри,
отколкото целевият метод приема в своята сигнатура, или когато за
целевото действие не може да се генерира URL. Как да се постъпи с
невалидните връзки определя статичната променлива
Presenter::$invalidLinkMode
. Тя може да приема комбинация от тези стойности
(константи):
Presenter::InvalidLinkSilent
– тих режим, като URL се връща знак #Presenter::InvalidLinkWarning
– хвърля се предупреждение E_USER_WARNING, което в продукционен режим ще бъде записано в лога, но няма да предизвика прекъсване на изпълнението на скриптаPresenter::InvalidLinkTextual
– визуално предупреждение, изписва грешката директно във връзкатаPresenter::InvalidLinkException
– хвърля се изключение InvalidLinkException
Настройката по подразбиране е InvalidLinkWarning
в продукционен режим
и InvalidLinkWarning | InvalidLinkTextual
в режим на разработка. InvalidLinkWarning
в продукционна среда не предизвиква прекъсване на скрипта, но
предупреждението ще бъде записано в лога. В режим на разработка то се
улавя от Tracy и показва bluescreen. 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
.