Création de liens URL
Créer des liens dans Nette est aussi simple que de pointer du doigt. Il suffit de viser et le framework fait tout le travail pour vous. Nous allons montrer :
- comment créer des liens dans les templates et ailleurs
- comment distinguer un lien vers la page actuelle
- que faire des liens invalides
Grâce au routage bidirectionnel, vous n'aurez jamais à écrire en dur les URL de votre application dans les templates ou le code, URL qui pourraient changer plus tard, ou à les composer de manière compliquée. Dans le lien, il suffit d'indiquer le presenter et l'action, de passer d'éventuels paramètres, et le framework générera l'URL lui-même. En fait, c'est très similaire à l'appel d'une fonction. Vous allez adorer ça.
Dans le template du presenter
Le plus souvent, nous créons des liens dans les templates et l'attribut n:href
est un excellent assistant :
<a n:href="Product:show">détail</a>
Notez qu'au lieu de l'attribut HTML href
, nous avons utilisé un n:attribut n:href
. Sa valeur n'est alors pas une URL,
comme ce serait le cas avec l'attribut href
, mais le nom du presenter et de l'action.
Cliquer sur le lien est, pour simplifier, quelque chose comme appeler la méthode ProductPresenter::renderShow()
.
Et si elle a des paramètres dans sa signature, nous pouvons l'appeler avec des arguments :
<a n:href="Product:show $product->id, $product->slug">détail du produit</a>
Il est également possible de passer des paramètres nommés. Le lien suivant passe le paramètre lang
avec la
valeur cs
:
<a n:href="Product:show $product->id, lang: cs">détail du produit</a>
Si la méthode ProductPresenter::renderShow()
n'a pas $lang
dans sa signature, elle peut récupérer
la valeur du paramètre en utilisant $lang = $this->getParameter('lang')
ou depuis une propriété.
Si les paramètres sont stockés dans un tableau, ils peuvent être développés avec l'opérateur ...
(dans Latte
2.x, l'opérateur (expand)
) :
{var $args = [$product->id, lang => cs]}
<a n:href="Product:show ...$args">détail du produit</a>
Les liens transmettent également automatiquement les paramètres persistants.
L'attribut n:href
est très pratique pour les balises HTML <a>
. Si nous voulons afficher le
lien ailleurs, par exemple dans du texte, nous utilisons {link}
:
L'adresse est : {link Home:default}
Dans le code
Pour créer un lien dans le presenter, la méthode link()
est utilisée :
$url = $this->link('Product:show', $product->id);
Les paramètres peuvent également être passés via un tableau, où des paramètres nommés peuvent également être spécifiés :
$url = $this->link('Product:show', [$product->id, 'lang' => 'cs']);
Les liens peuvent également être créés sans presenter, c'est à cela que sert LinkGenerator et sa méthode link()
.
Liens vers un presenter
Si la cible du lien est un presenter et une action, la syntaxe est la suivante :
[//] [[[[:]module:]presenter:]action | this] [#fragment]
Ce format est pris en charge par toutes les balises Latte et toutes les méthodes du presenter qui fonctionnent avec des liens,
c'est-à-dire n:href
, {link}
, {plink}
, link()
, lazyLink()
,
isLinkCurrent()
, redirect()
, redirectPermanent()
, forward()
,
canonicalize()
et aussi LinkGenerator. Ainsi, même si n:href
est
utilisé dans les exemples, n'importe laquelle de ces fonctions pourrait être là.
La forme de base est donc Presenter:action
:
<a n:href="Home:default">page d'accueil</a>
Si nous lions vers une action du presenter actuel, nous pouvons omettre son nom :
<a n:href="default">page d'accueil</a>
Si la cible est l'action default
, nous pouvons l'omettre, mais les deux-points doivent rester :
<a n:href="Home:">page d'accueil</a>
Les liens peuvent également pointer vers d'autres modules. Ici, les liens sont
distingués comme relatifs à un sous-module imbriqué, ou absolus. Le principe est analogue aux chemins sur disque, sauf que les
deux-points remplacent les barres obliques. Supposons que le presenter actuel fasse partie du module Front
, alors
nous écririons :
<a n:href="Shop:Product:show">lien vers Front:Shop:Product:show</a>
<a n:href=":Admin:Product:show">lien vers Admin:Product:show</a>
Un cas spécial est un lien vers soi-même, où nous spécifions this
comme cible.
<a n:href="this">rafraîchir</a>
Nous pouvons lier vers une partie spécifique de la page via un fragment après le signe dièse #
:
<a n:href="Home:#main">lien vers Home:default et le fragment #main</a>
Chemins absolus
Les liens générés à l'aide de link()
ou n:href
sont toujours des chemins absolus (c'est-à-dire
qu'ils commencent par /
), mais pas des URL absolues avec protocole et domaine comme https://domain
.
Pour générer une URL absolue, ajoutez deux barres obliques au début (par ex. n:href="//Home:"
). Ou vous pouvez
configurer le presenter pour ne générer que des liens absolus en définissant $this->absoluteUrls = true
.
Lien vers la page actuelle
La cible this
crée un lien vers la page actuelle :
<a n:href="this">rafraîchir</a>
En même temps, tous les paramètres spécifiés dans la signature de la méthode action<Action>()
ou
render<View>()
sont également transmis, si action<Action>()
n'est pas définie. Donc, si
nous sommes sur la page Product:show
avec id: 123
, le lien vers this
transmettra également
ce paramètre.
Bien sûr, il est possible de spécifier les paramètres directement :
<a n:href="this refresh: 1">rafraîchir</a>
La fonction isLinkCurrent()
vérifie si la cible du lien est identique à la page actuelle. Cela peut être
utilisé, par exemple, dans un template pour distinguer les liens, etc.
Les paramètres sont les mêmes que pour la méthode link()
, mais il est en plus possible de spécifier un
caractère générique *
à la place d'une action spécifiques, ce qui signifie n'importe quelle action du
presenter donné.
{if !isLinkCurrent('Admin:login')}
<a n:href="Admin:login">Connectez-vous</a>
{/if}
<li n:class="isLinkCurrent('Product:*') ? active">
<a n:href="Product:">...</a>
</li>
En combinaison avec n:href
dans un seul élément, une forme abrégée peut être utilisée :
<a n:class="isLinkCurrent() ? active" n:href="Home:">...</a>
Le caractère générique *
ne peut être utilisé qu'à la place de l'action, pas du presenter.
Pour vérifier si nous sommes dans un certain module ou son sous-module, utilisez la méthode
isModuleCurrent(moduleName)
.
<li n:class="isModuleCurrent('Forum:Users') ? active">
<a n:href="Product:">...</a>
</li>
Liens vers un signal
La cible d'un lien ne doit pas nécessairement être seulement un presenter et une action, mais aussi un signal (ils appellent la méthode
handle<Signal>()
). La syntaxe est alors la suivante :
[//] [sub-component:]signal! [#fragment]
Le signal est donc distingué par un point d'exclamation :
<a n:href="click!">signal</a>
Il est également possible de créer un lien vers le signal d'un sous-composant (ou sous-sous-composant) :
<a n:href="componentName:click!">signal</a>
Liens dans un composant
Parce que les composants sont des unités autonomes et
réutilisables qui ne devraient avoir aucun lien avec les presenters environnants, les liens fonctionnent un peu différemment
ici. L'attribut Latte n:href
et la balise {link}
ainsi que les méthodes de composant comme
link()
et autres considèrent la cible du lien toujours comme le nom d'un signal. Par conséquent, il n'est
même pas nécessaire d'inclure un point d'exclamation :
<a n:href="click">signal, pas une action</a>
Si nous voulions lier vers des presenters dans le template d'un composant, nous utiliserions la balise
{plink}
:
<a href={plink Home:default}>accueil</a>
ou dans le code
$this->getPresenter()->link('Home:default')
Alias
Parfois, il peut être utile d'attribuer un alias facile à mémoriser à une paire Presenter:action. Par exemple, nommer la
page d'accueil Front:Home:default
simplement home
ou Admin:Dashboard:default
comme
admin
.
Les alias sont définis dans la configuration sous la clé
application › aliases
:
application:
aliases:
home: Front:Home:default
admin: Admin:Dashboard:default
sign: Front:Sign:in
Dans les liens, ils sont ensuite écrits en utilisant un arobase, par exemple :
<a n:href="@admin">administration</a>
Ils sont également pris en charge dans toutes les méthodes fonctionnant avec des liens, comme redirect()
et
similaires.
Liens invalides
Il peut arriver que nous créions un lien invalide – soit parce qu'il mène à un presenter inexistant, soit parce qu'il
passe plus de paramètres que la méthode cible n'en accepte dans sa signature, soit lorsqu'une URL ne peut pas être générée
pour l'action cible. La manière de traiter les liens invalides est déterminée par la variable statique
Presenter::$invalidLinkMode
. Elle peut prendre une combinaison de ces valeurs (constantes) :
Presenter::InvalidLinkSilent
– mode silencieux, le caractère # est retourné comme URLPresenter::InvalidLinkWarning
– un avertissement E_USER_WARNING est généré, qui sera enregistré en mode production, mais n'interrompra pas l'exécution du scriptPresenter::InvalidLinkTextual
– avertissement visuel, affiche l'erreur directement dans le lienPresenter::InvalidLinkException
– une exception InvalidLinkException est levée
Le paramètre par défaut est InvalidLinkWarning
en mode production et
InvalidLinkWarning | InvalidLinkTextual
en mode développement. InvalidLinkWarning
en environnement de
production ne provoque pas l'interruption du script, mais l'avertissement sera enregistré. En environnement de développement, il
est intercepté par Tracy et affiche un écran bleu. InvalidLinkTextual
fonctionne en retournant un message d'erreur comme URL, commençant par les caractères #error:
. Pour rendre ces
liens visibles au premier coup d'œil, ajoutons à notre CSS :
a[href^="#error:"] {
background: red;
color: white;
}
Si nous ne voulons pas que des avertissements soient produits en environnement de développement, nous pouvons définir le mode silencieux directement dans la configuration.
application:
silentLinks: true
LinkGenerator
Comment créer des liens avec un confort similaire à celui de la méthode link()
, mais sans la présence d'un
presenter ? C'est là qu'intervient Nette\Application\LinkGenerator.
LinkGenerator est un service que vous pouvez vous faire passer via le constructeur et ensuite créer des liens avec sa méthode
link()
.
Il y a une différence par rapport aux presenters. LinkGenerator crée tous les liens directement comme des URL absolues. De
plus, il n'y a pas de “presenter actuel”, il n'est donc pas possible de spécifier uniquement le nom de l'action comme cible
link('default')
ou d'utiliser des chemins relatifs vers les modules.
Les liens invalides lèvent toujours Nette\Application\UI\InvalidLinkException
.