Створення 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>

При цьому передаються всі параметри, зазначені в сигнатурі методу 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')

Може трапитися так, що ми створимо некоректне посилання – або через те, що воно посилається на неіснуючий презентер, або через те, що воно передає більше параметрів, ніж цільовий метод отримує у своїй сигнатурі, або коли не може бути згенеровано 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