Criando Links URL
Criar links no Nette é tão simples quanto apontar o dedo. Basta apontar e o framework faz todo o trabalho por você. Vamos mostrar:
- como criar links em templates e em outros lugares
- como distinguir um link para a página atual
- o que fazer com links inválidos
Graças ao roteamento bidirecional, você nunca precisará escrever URLs fixas da sua aplicação em templates ou código, que podem mudar posteriormente, ou montá-las de forma complicada. No link, basta indicar o presenter e a ação, passar quaisquer parâmetros e o framework gerará a URL por si só. Na verdade, é muito semelhante a chamar uma função. Você vai gostar disso.
No template do presenter
Mais frequentemente, criamos links em templates e um ótimo auxiliar é o atributo n:href
:
<a n:href="Product:show">detalhe</a>
Observe que, em vez do atributo HTML href
, usamos o n:atributo n:href
. Seu valor não é uma URL, como seria
no caso do atributo href
, but o nome do presenter e da ação.
Clicar no link é, simplificadamente, algo como chamar o método ProductPresenter::renderShow()
. E se ele tiver
parâmetros em sua assinatura, podemos chamá-lo com argumentos:
<a n:href="Product:show $product->id, $product->slug">detalhe do produto</a>
Também é possível passar parâmetros nomeados. O link a seguir passa o parâmetro lang
com o valor
pt
:
<a n:href="Product:show $product->id, lang: pt">detalhe do produto</a>
Se o método ProductPresenter::renderShow()
não tiver $lang
em sua assinatura, ele pode obter
o valor do parâmetro usando $lang = $this->getParameter('lang')
ou da propriedade.
Se os parâmetros estiverem armazenados em um array, eles podem ser expandidos com o operador ...
(no Latte 2.x,
com o operador (expand)
):
{var $args = [$product->id, lang => pt]}
<a n:href="Product:show ...$args">detalhe do produto</a>
Nos links, os chamados parâmetros persistentes também são transmitidos automaticamente.
O atributo n:href
é muito útil para tags HTML <a>
. Se quisermos exibir o link em outro
lugar, por exemplo, no texto, usamos {link}
:
O endereço é: {link Home:default}
No código
Para criar um link no presenter, usa-se o método link()
:
$url = $this->link('Product:show', $product->id);
Os parâmetros também podem ser passados através de um array, onde também podem ser especificados parâmetros nomeados:
$url = $this->link('Product:show', [$product->id, 'lang' => 'pt']);
Links também podem ser criados sem um presenter, para isso existe o LinkGenerator e seu
método link()
.
Links para o presenter
Se o destino do link for um presenter e uma ação, ele tem esta sintaxe:
[//] [[[[:]module:]presenter:]action | this] [#fragment]
O formato é suportado por todas as tags Latte e todos os métodos do presenter que trabalham com links, ou seja,
n:href
, {link}
, {plink}
, link()
, lazyLink()
,
isLinkCurrent()
, redirect()
, redirectPermanent()
, forward()
,
canonicalize()
e também LinkGenerator. Portanto, mesmo que n:href
seja
usado nos exemplos, qualquer uma das funções poderia estar lá.
A forma básica é, portanto, Presenter:action
:
<a n:href="Home:default">página inicial</a>
Se estivermos vinculando a uma ação do presenter atual, podemos omitir seu nome:
<a n:href="default">página inicial</a>
Se o destino for a ação default
, podemos omiti-la, mas os dois pontos devem permanecer:
<a n:href="Home:">página inicial</a>
Links também podem apontar para outros módulos. Aqui, os links são
distinguidos entre relativos para um submódulo aninhado ou absolutos. O princípio é análogo aos caminhos no disco, apenas em
vez de barras, são dois pontos. Suponha que o presenter atual faça parte do módulo Front
, então escrevemos:
<a n:href="Shop:Product:show">link para Front:Shop:Product:show</a>
<a n:href=":Admin:Product:show">link para Admin:Product:show</a>
Um caso especial é um link para si mesmo, onde especificamos this
como destino.
<a n:href="this">atualizar</a>
Podemos vincular a uma parte específica da página através do chamado fragmento após o caractere de cerquilha
#
:
<a n:href="Home:#main">link para Home:default e fragmento #main</a>
Caminhos absolutos
Links gerados usando link()
ou n:href
são sempre caminhos absolutos (ou seja, começam com
o caractere /
), mas não URLs absolutas com protocolo e domínio como https://domain
.
Para gerar uma URL absoluta, adicione duas barras no início (por exemplo, n:href="//Home:"
). Ou você pode
configurar o presenter para gerar apenas links absolutos definindo $this->absoluteUrls = true
.
Link para a página atual
O destino this
cria um link para a página atual:
<a n:href="this">atualizar</a>
Ao mesmo tempo, todos os parâmetros especificados na assinatura do método action<Action>()
ou
render<View>()
são transmitidos, se action<Action>()
não estiver definida. Portanto, se
estivermos na página Product:show
e id: 123
, o link para this
também passará este
parâmetro.
Claro, é possível especificar os parâmetros diretamente:
<a n:href="this refresh: 1">atualizar</a>
A função isLinkCurrent()
verifica se o destino do link é idêntico à página atual. Isso pode ser usado, por
exemplo, em um template para diferenciar links, etc.
Os parâmetros são os mesmos do método link()
, mas adicionalmente é possível usar o caractere curinga
*
em vez de uma ação específica, o que significa qualquer ação do presenter dado.
{if !isLinkCurrent('Admin:login')}
<a n:href="Admin:login">Faça login</a>
{/if}
<li n:class="isLinkCurrent('Product:*') ? active">
<a n:href="Product:">...</a>
</li>
Em combinação com n:href
em um único elemento, uma forma abreviada pode ser usada:
<a n:class="isLinkCurrent() ? active" n:href="Home:">...</a>
O caractere curinga *
só pode ser usado no lugar da ação, não do presenter.
Para verificar se estamos em um determinado módulo ou seu submódulo, usamos o método
isModuleCurrent(moduleName)
.
<li n:class="isModuleCurrent('Forum:Users') ? active">
<a n:href="Product:">...</a>
</li>
Links para sinal
O destino de um link não precisa ser apenas um presenter e uma ação, mas também um sinal (eles chamam o método
handle<Signal>()
). Então a sintaxe é a seguinte:
[//] [sub-component:]signal! [#fragment]
O sinal é, portanto, distinguido por um ponto de exclamação:
<a n:href="click!">sinal</a>
Também é possível criar um link para o sinal de um subcomponente (ou sub-subcomponente):
<a n:href="componentName:click!">sinal</a>
Links no componente
Como os componentes são unidades reutilizáveis separadas que
não devem ter vínculos com os presenters circundantes, os links funcionam um pouco diferente aqui. O atributo Latte
n:href
e a tag {link}
, bem como os métodos do componente como link()
e outros, consideram
o destino do link sempre como o nome de um sinal. Portanto, nem mesmo é necessário incluir o ponto de
exclamação:
<a n:href="click">sinal, não ação</a>
Se quiséssemos vincular a presenters no template do componente, usaríamos a tag {plink}
:
<a href={plink Home:default}>início</a>
ou no código
$this->getPresenter()->link('Home:default')
Aliases
Às vezes, pode ser útil atribuir um alias fácil de lembrar a um par Presenter:action. Por exemplo, nomear a página inicial
Front:Home:default
simplesmente como home
ou Admin:Dashboard:default
como
admin
.
Aliases são definidos na configuração sob a chave
application › aliases
:
application:
aliases:
home: Front:Home:default
admin: Admin:Dashboard:default
sign: Front:Sign:in
Nos links, eles são então escritos usando um arroba, por exemplo:
<a n:href="@admin">administração</a>
Eles também são suportados em todos os métodos que trabalham com links, como redirect()
e similares.
Links inválidos
Pode acontecer que criemos um link inválido – seja porque ele leva a um presenter inexistente, ou porque passa mais
parâmetros do que o método de destino aceita em sua assinatura, ou quando uma URL não pode ser gerada para a ação de
destino. Como lidar com links inválidos é determinado pela variável estática Presenter::$invalidLinkMode
. Ela
pode assumir uma combinação destes valores (constantes):
Presenter::InvalidLinkSilent
– modo silencioso, o caractere # é retornado como URLPresenter::InvalidLinkWarning
– um aviso E_USER_WARNING é lançado, que será registrado no modo de produção, mas não causará a interrupção da execução do scriptPresenter::InvalidLinkTextual
– aviso visual, exibe o erro diretamente no linkPresenter::InvalidLinkException
– a exceção InvalidLinkException é lançada
A configuração padrão é InvalidLinkWarning
no modo de produção e
InvalidLinkWarning | InvalidLinkTextual
no modo de desenvolvimento. InvalidLinkWarning
no ambiente de
produção não causa a interrupção do script, mas o aviso será registrado. No ambiente de desenvolvimento, ele é capturado
pelo Tracy e exibe uma bluescreen. InvalidLinkTextual
funciona retornando
uma mensagem de erro como URL, que começa com os caracteres #error:
. Para tornar esses links visíveis à primeira
vista, adicionamos ao CSS:
a[href^="#error:"] {
background: red;
color: white;
}
Se não quisermos que avisos sejam produzidos no ambiente de desenvolvimento, podemos definir o modo silencioso diretamente na configuração.
application:
silentLinks: true
LinkGenerator
Como criar links com conforto semelhante ao método link()
, mas sem a presença de um presenter? Para isso existe
a Nette\Application\LinkGenerator.
LinkGenerator é um serviço que você pode solicitar via construtor e, em seguida, criar links usando seu método
link()
.
Há uma diferença em relação aos presenters. O LinkGenerator cria todos os links diretamente como URLs absolutas. Além
disso, não existe um “presenter atual”, então não é possível especificar apenas o nome da ação como destino
link('default')
ou usar caminhos relativos para módulos.
Links inválidos sempre lançam Nette\Application\UI\InvalidLinkException
.