Створення 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_WARNING
  • Presenter::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.

версію: 4.0