Creación de enlaces URL

Crear enlaces en Nette es tan simple como señalar con el dedo. Solo necesita apuntar y el framework hará todo el trabajo por usted. Mostraremos:

  • cómo crear enlaces en plantillas y en otros lugares
  • cómo distinguir un enlace a la página actual
  • qué hacer con los enlaces no válidos

Gracias al enrutamiento bidireccional, nunca tendrá que escribir direcciones URL de su aplicación directamente en plantillas o código, que pueden cambiar más tarde, o componerlas de forma complicada. En el enlace, basta con indicar el presenter y la acción, pasar los parámetros necesarios y el framework generará la URL por sí mismo. De hecho, es muy similar a llamar a una función. Esto le gustará.

En la plantilla del presenter

La mayoría de las veces creamos enlaces en plantillas y un excelente ayudante es el atributo n:href:

<a n:href="Product:show">detalle</a>

Observe que en lugar del atributo HTML href, usamos el n:atributo n:href. Su valor no es una URL, como sería el caso del atributo href, sino el nombre del presenter y la acción.

Hacer clic en un enlace es, simplificando, algo así como llamar al método ProductPresenter::renderShow(). Y si tiene parámetros en su firma, podemos llamarlo con argumentos:

<a n:href="Product:show $product->id, $product->slug">detalle del producto</a>

También es posible pasar parámetros con nombre. El siguiente enlace pasa el parámetro lang con el valor cs:

<a n:href="Product:show $product->id, lang: cs">detalle del producto</a>

Si el método ProductPresenter::renderShow() no tiene $lang en su firma, puede obtener el valor del parámetro usando $lang = $this->getParameter('lang') o desde la propiedad.

Si los parámetros están almacenados en un array, se pueden expandir con el operador ... (en Latte 2.x con el operador (expand)):

{var $args = [$product->id, lang => cs]}
<a n:href="Product:show ...$args">detalle del producto</a>

En los enlaces también se pasan automáticamente los llamados parámetros persistentes.

El atributo n:href es muy útil para las etiquetas HTML <a>. Si queremos mostrar el enlace en otro lugar, por ejemplo en el texto, usamos {link}:

La dirección es: {link Home:default}

En el código

Para crear un enlace en el presenter, se utiliza el método link():

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

Los parámetros también se pueden pasar mediante un array, donde también se pueden indicar parámetros con nombre:

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

Los enlaces también se pueden crear sin un presenter, para eso está LinkGenerator y su método link().

Enlaces a presenter

Si el destino del enlace es un presenter y una acción, tiene esta sintaxis:

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

El formato es compatible con todas las etiquetas Latte y todos los métodos del presenter que trabajan con enlaces, es decir, n:href, {link}, {plink}, link(), lazyLink(), isLinkCurrent(), redirect(), redirectPermanent(), forward(), canonicalize() y también LinkGenerator. Así que, aunque en los ejemplos se use n:href, podría estar cualquiera de las funciones.

La forma básica es, por lo tanto, Presenter:action:

<a n:href="Home:default">página de inicio</a>

Si enlazamos a una acción del presenter actual, podemos omitir su nombre:

<a n:href="default">página de inicio</a>

Si el destino es la acción default, podemos omitirla, pero los dos puntos deben permanecer:

<a n:href="Home:">página de inicio</a>

Los enlaces también pueden apuntar a otros módulos. Aquí, los enlaces se distinguen entre relativos a un submódulo anidado o absolutos. El principio es análogo a las rutas en el disco, solo que en lugar de barras inclinadas hay dos puntos. Supongamos que el presenter actual es parte del módulo Front, entonces escribimos:

<a n:href="Shop:Product:show">enlace a Front:Shop:Product:show</a>
<a n:href=":Admin:Product:show">enlace a Admin:Product:show</a>

Un caso especial es un enlace a sí mismo, donde indicamos this como destino.

<a n:href="this">refrescar</a>

Podemos enlazar a una parte específica de la página a través del llamado fragmento después del signo de almohadilla #:

<a n:href="Home:#main">enlace a Home:default y fragmento #main</a>

Rutas absolutas

Los enlaces generados mediante link() o n:href son siempre rutas absolutas (es decir, comienzan con el carácter /), pero no URL absolutas con protocolo y dominio como https://domain.

Para generar una URL absoluta, agregue dos barras inclinadas al principio (p. ej., n:href="//Home:"). O se puede cambiar el presenter para que genere solo enlaces absolutos estableciendo $this->absoluteUrls = true.

Enlace a la página actual

El destino this crea un enlace a la página actual:

<a n:href="this">refrescar</a>

Al mismo tiempo, se transfieren todos los parámetros indicados en la firma del método action<Action>() o render<View>(), si action<Action>() no está definida. Así que si estamos en la página Product:show e id: 123, el enlace a this también pasará este parámetro.

Por supuesto, es posible especificar los parámetros directamente:

<a n:href="this refresh: 1">refrescar</a>

La función isLinkCurrent() comprueba si el destino del enlace coincide con la página actual. Esto se puede usar, por ejemplo, en la plantilla para distinguir enlaces, etc.

Los parámetros son los mismos que en el método link(), pero además es posible indicar un comodín * en lugar de una acción específica, que significa cualquier acción del presenter dado.

{if !isLinkCurrent('Admin:login')}
	<a n:href="Admin:login">Inicie sesión</a>
{/if}

<li n:class="isLinkCurrent('Product:*') ? active">
	<a n:href="Product:">...</a>
</li>

En combinación con n:href en un solo elemento, se puede usar una forma abreviada:

<a n:class="isLinkCurrent() ? active" n:href="Home:">...</a>

El comodín * solo se puede usar en lugar de la acción, nikoliv presenteru.

Para determinar si estamos en un módulo específico o en su submódulo, usamos el método isModuleCurrent(moduleName).

<li n:class="isModuleCurrent('Forum:Users') ? active">
	<a n:href="Product:">...</a>
</li>

Enlaces a señal

El destino de un enlace no tiene por qué ser solo un presenter y una acción, sino también una señal (llaman al método handle<Signal>()). Entonces la sintaxis es la siguiente:

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

La señal se distingue por el signo de exclamación:

<a n:href="click!">señal</a>

También se puede crear un enlace a la señal de un subcomponente (o sub-subcomponente):

<a n:href="componentName:click!">señal</a>

Enlaces en componente

Dado que los componentes son unidades reutilizables independientes que no deberían tener ninguna vinculación con los presenters circundantes, los enlaces funcionan aquí de manera un poco diferente. El atributo Latte n:href y la etiqueta {link}, así como los métodos del componente como link() y otros, consideran el destino del enlace siempre como el nombre de la señal. Por lo tanto, ni siquiera es necesario indicar el signo de exclamación:

<a n:href="click">señal, no acción</a>

Si quisiéramos enlazar a presenters en la plantilla del componente, usaríamos la etiqueta {plink}:

<a href={plink Home:default}>inicio</a>

o en el código

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

Alias

A veces puede ser útil asignar un alias fácil de recordar al par Presenter:acción. Por ejemplo, nombrar la página de inicio Front:Home:default simplemente como home o Admin:Dashboard:default como admin.

Los alias se definen en la configuración bajo la clave application › aliases:

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

En los enlaces, luego se escriben usando arroba, por ejemplo:

<a n:href="@admin">administración</a>

También son compatibles con todos los métodos que trabajan con enlaces, como redirect() y similares.

Enlaces no válidos

Puede suceder que creemos un enlace no válido, ya sea porque apunta a un presenter inexistente, o porque pasa más parámetros de los que el método de destino acepta en su firma, o cuando no se puede generar una URL para la acción de destino. Cómo tratar los enlaces no válidos lo determina la variable estática Presenter::$invalidLinkMode. Esta puede tomar una combinación de estos valores (constantes):

  • Presenter::InvalidLinkSilent – modo silencioso, se devuelve el carácter # como URL
  • Presenter::InvalidLinkWarning – se lanza una advertencia E_USER_WARNING, que se registrará en modo de producción, pero no causará la interrupción de la ejecución del script
  • Presenter::InvalidLinkTextual – advertencia visual, muestra el error directamente en el enlace
  • Presenter::InvalidLinkException – se lanza la excepción InvalidLinkException

La configuración predeterminada es InvalidLinkWarning en modo de producción y InvalidLinkWarning | InvalidLinkTextual en desarrollo. InvalidLinkWarning en el entorno de producción no causa la interrupción del script, pero la advertencia se registrará. En el entorno de desarrollo, Tracy lo captura y muestra una pantalla azul. InvalidLinkTextual funciona devolviendo un mensaje de error como URL, que comienza con los caracteres #error:. Para que dichos enlaces sean evidentes a primera vista, agregaremos a nuestro CSS:

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

Si no queremos que se produzcan advertencias en el entorno de desarrollo, podemos establecer el modo silencioso directamente en la configuración.

application:
	silentLinks: true

LinkGenerator

¿Cómo crear enlaces con una comodidad similar a la del método link(), pero sin la presencia de un presenter? Para eso está Nette\Application\LinkGenerator.

LinkGenerator es un servicio que puede solicitar que se le pase a través del constructor y luego crear enlaces con su método link().

Hay una diferencia con respecto a los presenters. LinkGenerator crea todos los enlaces directamente como URL absolutas. Y además, no existe un “presenter actual”, por lo que no se puede indicar solo el nombre de la acción como destino link('default') ni indicar rutas relativas a módulos.

Los enlaces no válidos siempre lanzan Nette\Application\UI\InvalidLinkException.

versión: 4.0