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().

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.

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>

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>

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.

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 URL
  • Presenter::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 script
  • Presenter::InvalidLinkTextual – aviso visual, exibe o erro diretamente no link
  • Presenter::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.

versão: 4.0