Nette Documentation Preview

syntax
Створення URL-посилань
**********************

<div class=perex>

Створювати посилання в Nette так само просто, як тикати пальцем. Просто наведіть курсор, і система зробить усю роботу за вас. Ми покажемо:

- як створювати посилання в шаблонах та інших місцях
- як виділити посилання на поточну сторінку
- що робити з недійсними посиланнями

</div>


Завдяки [двонаправленій маршрутизації |routing], вам ніколи не доведеться жорстко кодувати URL додатка в шаблонах або коді, які можуть змінитися пізніше або бути складними для складання. Просто вкажіть презентера і дію в посиланні, передайте будь-які параметри, і фреймворк сам згенерує URL. Фактично, це дуже схоже на виклик функції. Вам сподобається.


У шаблоні презентера .[#toc-in-the-presenter-template]
======================================================

Найчастіше ми створюємо посилання в шаблонах, і чудовим помічником є атрибут `n:href`:

```latte
<a n:href="Product:show">подробнее</a>
```

Зверніть увагу, що замість HTML-атрибута `href` ми використовували [n:attribute |latte:syntax#n:attributes] `n:href`. Його значенням є не URL, як ви звикли бачити в атрибуті `href`, а ім'я презентера та дія.

Натискання на посилання, простіше кажучи, є чимось на зразок виклику методу `ProductPresenter::renderShow()`. І якщо в його сигнатурі є параметри, ми можемо викликати його з аргументами:

```latte
<a n:href="Product:show $product->id, $product->slug">подробнее</a>
```

Також можна передавати іменовані параметри. Наступне посилання передає параметр `lang` зі значенням `en`:

```latte
<a n:href="Product:show $product->id, lang: en">подробнее</a>
```

Якщо метод `ProductPresenter::renderShow()` не має `$lang` у своїй сигнатурі, він може отримати значення параметра за допомогою `$lang = $this->getParameter('lang')` або з [властивості |presenters#Request Parameters].

Якщо параметри зберігаються в масиві, їх можна розширити за допомогою оператора `(expand)` (щось на зразок оператора `...` у PHP, але працює з асоціативними масивами):

```latte
{var $args = [$product->id, lang => en]}
<a n:href="Product:show (expand) $args">подробнее</a>
```

Так звані [постійні параметри |presenters#Persistent-Parameters] також автоматично передаються в посиланнях.

Атрибут `n:href` дуже зручний для HTML-тегів `<a>`. Якщо ми хочемо вивести посилання в іншому місці, наприклад, у тексті, ми використовуємо `{link}`:

```latte
URL: {link Home:default}
```


У коді .[#toc-in-the-code]
==========================

Метод `link()` використовується для створення посилання в презентері:

```php
$url = $this->link('Product:show', $product->id);
```

Параметри також можуть бути передані у вигляді масиву, в якому також можуть бути вказані іменовані параметри:

```php
$url = $this->link('Product:show', [$product->id, 'lang' => 'cs']);
```

Посилання можна створювати і без презентера, використовуючи [LinkGenerator |#LinkGenerator] і його метод `link()`.


Посилання на презентер .[#toc-links-to-presenter]
=================================================

Якщо метою посилання є презентер і дія, воно має такий синтаксис:

```
[//] [[[[:]module:]presenter:]action | this] [#fragment]
```

Формат підтримується всіма тегами Latte і всіма методами презентера, які працюють із посиланнями, тобто `n:href`, `{link}`, `{plink}`, `link()`, `lazyLink()`, `isLinkCurrent()`, `redirect()`, `redirectPermanent()`, `forward()`, `canonicalize()`, а також [LinkGenerator |#LinkGenerator]. Тому, навіть якщо в прикладах використовується `n:href`, тут може бути будь-яка з функцій.

Тому основною формою є `Presenter:action`:

```latte
<a n:href="Home:default">главная страница</a>
```

Якщо ми посилаємося на дію поточного презентера, ми можемо опустити його ім'я:

```latte
<a n:href="default">главная страница</a>
```

Якщо дія є `default`, ми можемо опустити її, але двокрапка має залишитися:

```latte
<a n:href="Home:">главная страница</a>
```

Посилання можуть також вказувати на інші [модулі |modules]. Тут посилання розрізняються на відносні по відношенню до підмодулів або абсолютні. Принцип аналогічний дисковим шляхам, тільки замість косих рисок стоять двокрапки. Припустимо, що справжній презентер є частиною модуля `Front`, тоді ми напишемо:

```latte
<a n:href="Shop:Product:show">ссылка на Front:Shop:Product:show</a>
<a n:href=":Admin:Product:show">ссылка на Admin:Product:show</a>
```

Особливим випадком є [посилання на себе |#Link-to-Current-Page]. Тут ми напишемо `this` як ціль.

```latte
<a n:href="this">refresh</a>
```

Ми можемо посилатися на певну частину HTML-сторінки через так званий фрагмент після хеш-символу `#`:

```latte
<a n:href="Home:#main">ссылка на Home:default и фрагмент #main</a>
```


Абсолютні шляхи .[#toc-absolute-paths]
======================================

Посилання, що генеруються `link()` або `n:href`, завжди є абсолютними шляхами (тобто починаються з `/`), але не абсолютними URL з протоколом і доменом, як `https://domain`.

Щоб створити абсолютний URL, додайте дві косі риски на початок (наприклад, `n:href="//Home:"`). Або ви можете перемкнути презентатор на генерацію тільки абсолютних посилань, встановивши `$this->absoluteUrls = true`.


Посилання на поточну сторінку .[#toc-link-to-current-page]
==========================================================

Ціль `this` створить посилання на поточну сторінку:

```latte
<a n:href="this">обновить</a>
```

При цьому всі параметри, зазначені в підписі до файлу `action<Action>()` або `render<View>()` якщо метод `action<Action>()` не визначено, передаються. Отже, якщо ми знаходимося на сторінках `Product:show` і `id:123`, то посилання на `this` також передасть цей параметр.

Звичайно, можна вказати параметри безпосередньо:

```latte
<a n:href="this refresh: 1">обновить</a>
```

Метод презентера `isLinkCurrent()` визначає, чи збігається мета посилання з поточною сторінкою. Це можна використовувати, наприклад, у шаблоні для розмежування посилань тощо.

Параметри ті самі, що й для методу `link()`, але також можна використовувати підстановний знак `*` замість конкретної дії, що означає будь-яку дію презентера.

```latte
{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` в одному елементі:

```latte
<a n:class="$presenter->isLinkCurrent() ? active" n:href="Product:detail">...</a>
```

Символ підстановки `*` замінює тільки дію презентера, але не сам презентер.

Щоб дізнатися, чи перебуваємо ми в певному модулі або його підмодулі, ми можемо використовувати метод `$presenter->isModuleCurrent(moduleName)`.

```latte
<li n:class="$presenter->isModuleCurrent('MyEshop:Users') ? active">
	<a n:href="Product:">...</a>
</li>
```


Посилання на сигнал .[#toc-links-to-signal]
===========================================

Метою посилання може бути не тільки презентер і дія, а й [сигнал |components#Signal] (вони викликають метод `handle<Signal>()`). Синтаксис наступний:

```
[//] [sub-component:]signal! [#fragment]
```

Тому сигнал виділяється знаком оклику:

```latte
<a n:href="click!">signal</a>
```

Ви також можете створити посилання на сигнал підкомпонента (або підсубкомпонента):

```latte
<a n:href="componentName:click!">signal</a>
```


Посилання на компонент .[#toc-links-in-component]
=================================================

Оскільки [компоненти |components] є окремими багаторазово використовуваними одиницями, які не повинні мати жодних стосунків з оточуючими презентерами, посилання працюють дещо по-іншому. Атрибут Latte `n:href` і тег `{link}`, а також методи компонентів, такі як `link()` та інші, завжди розглядають ціль **як ім'я сигналу**. Тому немає необхідності використовувати знак оклику:

```latte
<a n:href="click">сигнал, не действие</a>
```

Якщо ми хочемо зробити посилання на презентери в шаблоні компонента, ми використовуємо тег `{plink}`:

```latte
<a href={plink Home:default}>главная страница</a>
```

or in the code

```php
$this->getPresenter()->link('Home:default')
```


Псевдоніми .[#toc-aliases]{data-version:v3.2.2}
===============================================

Іноді корисно присвоїти парі доповідач:дія псевдонім, який легко запам'ятовується. Наприклад, ви можете назвати домашню сторінку `Front:Home:default` просто як `home` або `Admin:Dashboard:default` як `admin`.

Псевдоніми визначаються у [конфігурації |configuration] за допомогою ключа `application › aliases`:

```neon
application:
    aliases:
        home: Front:Home:default
        admin: Admin:Dashboard:default
        sign: Front:Sign:in
```

У посиланнях вони пишуться за допомогою символу at, наприклад:

```latte
<a n:href="@admin">administration</a>
```

Вони підтримуються у всіх методах, які працюють з посиланнями, таких як `redirect()` та подібних.


Недійсні посилання .[#toc-invalid-links]
========================================

Може трапитися так, що ми створимо некоректне посилання - або через те, що воно посилається на неіснуючий презентер, або через те, що воно передає більше параметрів, ніж цільовий метод отримує у своїй сигнатурі, або коли не може бути згенеровано URL для цільової дії. Що робити з недійсними посиланнями, визначається статичною змінною `Presenter::$invalidLinkMode`. Вона може мати одне з цих значень (констант):

- `Presenter::InvalidLinkSilent` - тихий режим, повертає символ `#` як URL-адресу
- `Presenter::InvalidLinkWarning` - буде видано повідомлення E_USER_WARNING
- `Presenter::InvalidLinkTextual` - візуальне попередження, текст помилки відображається в посиланні
- `Presenter::InvalidLinkException` - буде викинуто виняток InvalidLinkException

За замовчуванням у робочому режимі використовується параметр `InvalidLinkWarning`, а в режимі розробки - `InvalidLinkWarning | InvalidLinkTextual`. `InvalidLinkWarning` не вбиває сценарій у робочому середовищі, але попередження буде зареєстровано в журналі. У середовищі розробки [Tracy |tracy:] перехопить попередження і відобразить синю сторінку помилки. Якщо встановлено `InvalidLinkTextual`, презентер і компоненти повертають повідомлення про помилку у вигляді URL-адреси, яку позначено `#error:`. Щоб зробити такі посилання видимими, ми можемо додати правило CSS до нашої таблиці стилів:

```css
a[href^="#error:"] {
	background: red;
	color: white;
}
```

Якщо ми не хочемо, щоб попередження створювалися в середовищі розробки, ми можемо ввімкнути режим автоматичного неприпустимого зв'язку в [конфігурації |configuration].

```neon
application:
	silentLinks: true
```


LinkGenerator .[#toc-linkgenerator]
===================================

Як створювати посилання з таким же комфортом, як з методом `link()`, але без презентера? Для цього в нас є [api:Nette\Application\LinkGenerator].

LinkGenerator - це сервіс, який можна передати через конструктор, а потім створити посилання за допомогою методу 'link()'.

Є різниця порівняно з презентерами. LinkGenerator створює всі посилання як абсолютні URL-адреси. Крім того, немає "поточного презентера", тому неможливо вказати тільки ім'я дії 'link('default')' або відносні шляхи до модулів.

Неприпустимі посилання завжди викидають виняток `Nette\Application\UI\InvalidLinkException`.

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