Nette Documentation Preview

syntax
Solución de problemas
*********************


Nette no funciona, aparece una página en blanco .[#toc-nette-is-not-working-white-page-is-displayed]
----------------------------------------------------------------------------------------------------
- Pruebe a poner `ini_set('display_errors', '1'); error_reporting(E_ALL);` después de `declare(strict_types=1);` en el archivo `index.php` para forzar la visualización de errores
- Si sigue viendo una pantalla blanca, probablemente haya un error en la configuración del servidor y descubrirá la razón en el registro del servidor. Para estar seguro, verifique si PHP está funcionando intentando imprimir algo usando `echo 'test';`.
- Si ve un error *Server Error: ¡Lo sentimos! ...*, continúe con la siguiente sección:


Error 500 *Error del servidor: ¡Lo sentimos! ...* .[#toc-error-500-server-error-we-re-sorry]
--------------------------------------------------------------------------------------------
Esta página de error es mostrada por Nette en modo de producción. Si la ve en su máquina de desarrollo, [cambie al modo de desarrollador |application:bootstrap#Development vs Production Mode] y Tracy se mostrará con un informe detallado.

Siempre podrá encontrar el motivo del error en el directorio `log/`. Sin embargo, si el mensaje de error muestra la frase `Tracy is unable to log error`, primero determine por qué no se pueden registrar los errores. Puede hacerlo, por ejemplo, [cambiando |application:bootstrap#Development vs Production Mode] temporalmente al modo de desarrollador y dejando que Tracy registre cualquier cosa después de su lanzamiento:

```php
// Bootstrap.php
$configurator->setDebugMode('23.75.345.200'); // su dirección IP
$configurator->enableTracy($rootDir . '/log');
\Tracy\Debugger::log('hello');
```

Tracy le informará de por qué no puede registrar. La causa puede ser la [falta de permisos |#Setting Directory Permissions] para escribir en el directorio `log/`.

Una de las razones más comunes de un error 500 es una caché obsoleta. Mientras que Nette actualiza la caché de forma inteligente y automática en modo desarrollo, en modo producción se centra en maximizar el rendimiento, y limpiar la caché después de cada modificación de código depende de ti. Intente borrar `temp/cache`.


Error 404, enrutamiento no funciona .[#toc-error-404-routing-not-working]
-------------------------------------------------------------------------
Cuando todas las páginas (excepto la página de inicio) devuelven un error 404, parece un problema de configuración del servidor para [URLs bonitas |#How to Configure a Server for Nice URLs?].


¿Cómo desactivar la caché durante el desarrollo? .[#toc-how-to-disable-cache-during-development]
------------------------------------------------------------------------------------------------
Nette es inteligente, y no necesitas desactivar la caché en él. Durante el desarrollo, actualiza automáticamente la caché cada vez que hay un cambio en la plantilla o en la configuración del contenedor DI. Además, el modo de desarrollo se activa por auto-detección, por lo que normalmente no hay necesidad de configurar nada, [o sólo la dirección IP |application:bootstrap#development-vs-production-mode].

A la hora de depurar el router, recomendamos desactivar la caché del navegador, donde, por ejemplo, podrían almacenarse las redirecciones: abre Herramientas de desarrollo (Ctrl+Mayús+I o Cmd+Opción+I) y, en el panel Red, marca la casilla para desactivar la caché.


Error `#[\ReturnTypeWillChange] attribute should be used` .[#toc-error-returntypewillchange-attribute-should-be-used]
---------------------------------------------------------------------------------------------------------------------
Este error se produce si ha actualizado PHP a la versión 8.1 pero está utilizando Nette, que no es compatible con ella. Entonces la solución es actualizar Nette a una versión más reciente usando `composer update`. Nette es compatible con PHP 8.1 desde la versión 3.0. Si está usando una versión anterior (puede averiguarlo buscando en `composer.json`), [actualice |migrations:en] Nette o quédese con PHP 8.0.


Configuración de permisos de directorio .[#toc-setting-directory-permissions]
-----------------------------------------------------------------------------
Si está desarrollando en macOS o Linux (o cualquier otro sistema basado en Unix), necesita configurar los privilegios de escritura en el servidor web. Suponiendo que su aplicación se encuentra en el directorio por defecto `/var/www/html` (Fedora, CentOS, RHEL)

```shell
cd /var/www/html/MY_PROJECT
chmod -R a+rw temp log
```

En algunos sistemas Linux (Fedora, CentOS, ...) SELinux puede estar activado por defecto. Es posible que tenga que actualizar las políticas de SELinux o configurar las rutas de los directorios `temp` y `log` con el contexto de seguridad SELinux correcto. Los directorios `temp` y `log` deben configurarse con el contexto `httpd_sys_rw_content_t`; para el resto de la aplicación -- principalmente la carpeta `app` -- el contexto `httpd_sys_content_t` será suficiente. Ejecutar en el servidor como root:

```shell
semanage fcontext -at httpd_sys_rw_content_t '/var/www/html/MY_PROJECT/log(/.*)?'
semanage fcontext -at httpd_sys_rw_content_t '/var/www/html/MY_PROJECT/temp(/.*)?'
restorecon -Rv /var/www/html/MY_PROJECT/
```

A continuación, es necesario activar el booleano de SELinux `httpd_can_network_connect_db` para permitir que Nette se conecte a la base de datos a través de la red. Por defecto, está desactivado. El comando `setsebool` se puede utilizar para realizar esta tarea, y si se especifica la opción `-P`, esta configuración será persistente a través de reinicios.

```shell
setsebool -P httpd_can_network_connect_db on
```


¿Cómo cambiar o eliminar el directorio `www` de la URL? .[#toc-how-to-change-or-remove-www-directory-from-url]
--------------------------------------------------------------------------------------------------------------
El directorio `www/` utilizado en los proyectos de ejemplo de Nette es el denominado directorio público o raíz documental del proyecto. Es el único directorio cuyo contenido es accesible para el navegador. Y contiene el archivo `index.php`, el punto de entrada que inicia una aplicación web escrita en Nette.

Para ejecutar la aplicación en el hosting, es necesario establecer el document-root a este directorio en la configuración del hosting. O, si el alojamiento tiene una carpeta pre-hecha para el directorio público con un nombre diferente (por ejemplo `web`, `public_html` etc.), simplemente renombre `www/`.

La solución **no es** impedir el acceso a todas las carpetas excepto `www/` mediante reglas en el archivo `.htaccess` o en el router. Si tu alojamiento no permite establecer la raíz del documento en un subdirectorio (es decir, crear directorios un nivel por encima del directorio público), deberías buscar otro servicio de alojamiento. De lo contrario, te estarías exponiendo a importantes riesgos de seguridad. Sería como vivir en un apartamento donde la puerta principal no se puede cerrar y está siempre abierta de par en par.


¿Cómo configurar un servidor para URLs agradables? .[#toc-how-to-configure-a-server-for-nice-urls]
--------------------------------------------------------------------------------------------------
**Apache**: debe activar y establecer reglas mod_rewrite en el archivo `.htaccess`:

```apacheconf
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule !\.(pdf|js|ico|gif|jpg|png|css|rar|zip|tar\.gz)$ index.php [L]
```

Si tiene problemas, asegúrese de que
- el archivo `.htaccess` se encuentra en el directorio document-root (es decir, junto al archivo `index.php` )
- [Apache está procesando los archivos .htaccess |#Test if .htaccess is working]
- [mod_rewrite está activado |#Test if mod_rewrite is enabled]

Si está configurando la aplicación en una subcarpeta, es posible que tenga que descomentar la línea para la configuración de `RewriteBase` y establecerla en la carpeta correcta.

**nginx**: la directiva `try_files` debe utilizarse en la configuración del servidor:

```nginx
location / {
	try_files $uri $uri/ /index.php$is_args$args;  # $is_args$args ¡ES IMPORTANTE!
}
```

El bloque `location` debe definirse exactamente una vez para cada ruta del sistema de ficheros en el bloque `server`. Si ya tiene un bloque `location /` en su configuración, añada la directiva `try_files` al bloque existente.


Compruebe si `.htaccess` funciona .[#toc-test-if-htaccess-is-working]
---------------------------------------------------------------------
La forma más sencilla de probar si Apache usa o ignora su fichero `.htaccess`, es romperlo intencionadamente. Ponga la línea `Test` al principio del archivo y ahora, si actualiza la página en su navegador, debería ver un *Internal Server Error*.

Si ve este error, ¡en realidad es bueno! Esto significa que Apache está analizando el archivo `.htaccess`, y encuentra el error que hemos puesto allí. Elimine la línea `Test`.

Si no ve un *Error Interno del Servidor*, su configuración de Apache ignora el fichero `.htaccess`. Generalmente, Apache lo ignora porque falta la directiva de configuración `AllowOverride All`.

Si lo aloja usted mismo, es bastante fácil de arreglar. Abra su `httpd.conf` o `apache.conf` en un editor de texto, localice la sección relevante y añada/cambie la directiva `<Directory>` y añada/cambie la directiva:

```apacheconf
<Directory "/var/www/htdocs"> # path to your document root
    AllowOverride All
    ...
```

Si su sitio está alojado en otro lugar, compruebe su panel de control para ver si puede activar `.htaccess` allí. Si no es así, póngase en contacto con su proveedor de alojamiento para que lo haga por usted.


Compruebe si `mod_rewrite` está habilitado .[#toc-test-if-mod-rewrite-is-enabled]
---------------------------------------------------------------------------------
Si ha comprobado que [`.htaccess` funciona |#Test if .htaccess is working], puede verificar que la extensión mod_rewrite está habilitada. Ponga la línea `RewriteEngine On` al principio del archivo `.htaccess` y actualice la página en su navegador.
Si ves un *Internal Server Error*, significa que mod_rewrite no está habilitado. Hay varias formas de activarlo. Consulte Stack Overflow para ver las distintas formas de hacerlo en diferentes configuraciones.


Los enlaces se generan sin `https:` .[#toc-links-are-generated-without-https]
-----------------------------------------------------------------------------
Nette genera enlaces con el mismo protocolo que utiliza la página actual. Así, en la página `https://foo` y viceversa.
Si estás detrás de un proxy inverso que elimina HTTPS (por ejemplo, en Docker), entonces necesitas [establecer un proxy |http:configuration#HTTP proxy] en la configuración para que la detección de protocolo funcione correctamente.

Si usas Nginx como proxy, necesitas tener la redirección configurada así:

```
location / {
	proxy_set_header Host $host;
	proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
	proxy_set_header X-Forwarded-Proto $scheme;
	proxy_set_header X-Forwarded-Port  $server_port;
	proxy_pass http://IP-aplikace:80;  # IP o nombre de host del servidor/contenedor donde se ejecuta la aplicación
}
```

A continuación, debe especificar el proxy IP y, si procede, el rango IP de su red local donde ejecuta la infraestructura:

```neon
http:
	proxy: IP-proxy/IP-range
```


Uso de caracteres { } en JavaScript .[#toc-use-of-characters-in-javascript]
---------------------------------------------------------------------------
Los caracteres `{` and `}` se utilizan para escribir etiquetas Latte. Todo (excepto el espacio y las comillas) después de `{` character is considered a tag. If you need to print character `{` (a menudo en JavaScript), puede poner un espacio (u otro carácter vacío) justo después de `{`. De esta manera se evita que se interprete como una etiqueta.

Si es necesario imprimir estos caracteres en una situación en la que se interpretarían como una etiqueta, puede utilizar etiquetas especiales para imprimir estos caracteres: `{l}` para `{` and `{r}` para `}`.

```
{is tag}
{ is not tag }
{l}is not tag{r}
```


Observe `Presenter::getContext() is deprecated` .[#toc-notice-presenter-getcontext-is-deprecated]
-------------------------------------------------------------------------------------------------

Nette es de lejos el primer framework PHP que cambió a la inyección de dependencias y llevó a los programadores a usarla de forma consistente, empezando por los presentadores. Si un presentador necesita una dependencia, [la pedirá |dependency-injection:passing-dependencies].
Por el contrario, la forma en que pasamos todo el contenedor DI a una clase y ésta extrae las dependencias de él directamente se considera un antipatrón (se llama localizador de servicios).
Esta forma se utilizaba en Nette 0.x antes de la llegada de la inyección de dependencias, y su reliquia es el método `Presenter::getContext()`, hace tiempo marcado como obsoleto.

Si portas una aplicación Nette muy antigua, puedes encontrar que todavía utiliza este método. Así que desde la versión 3.1 de `nette/application` se encontrará con la advertencia `Nette\Application\UI\Presenter::getContext() is deprecated, use dependency injection`, desde la versión 4.0 se encontrará con el error de que el método no existe.

La solución limpia, por supuesto, es rediseñar la aplicación para pasar dependencias usando inyección de dependencias. Como solución alternativa, puede añadir su propio método `getContext()` a su presentador base y saltarse el mensaje:

```php
abstract BasePresenter extends Nette\Application\UI\Presenter
{
	private Nette\DI\Container $context;

	public function injectContext(Nette\DI\Container $context)
	{
		$this->context = $context;
	}

	public function getContext(): Nette\DI\Container
	{
		return $this->context;
	}
}
```


{{leftbar: www:@menu-common}}

Solución de problemas

Nette no funciona, aparece una página en blanco

  • Pruebe a poner ini_set('display_errors', '1'); error_reporting(E_ALL); después de declare(strict_types=1); en el archivo index.php para forzar la visualización de errores
  • Si sigue viendo una pantalla blanca, probablemente haya un error en la configuración del servidor y descubrirá la razón en el registro del servidor. Para estar seguro, verifique si PHP está funcionando intentando imprimir algo usando echo 'test';.
  • Si ve un error Server Error: ¡Lo sentimos! …, continúe con la siguiente sección:

Error 500 Error del servidor: ¡Lo sentimos! …

Esta página de error es mostrada por Nette en modo de producción. Si la ve en su máquina de desarrollo, cambie al modo de desarrollador y Tracy se mostrará con un informe detallado.

Siempre podrá encontrar el motivo del error en el directorio log/. Sin embargo, si el mensaje de error muestra la frase Tracy is unable to log error, primero determine por qué no se pueden registrar los errores. Puede hacerlo, por ejemplo, cambiando temporalmente al modo de desarrollador y dejando que Tracy registre cualquier cosa después de su lanzamiento:

// Bootstrap.php
$configurator->setDebugMode('23.75.345.200'); // su dirección IP
$configurator->enableTracy($rootDir . '/log');
\Tracy\Debugger::log('hello');

Tracy le informará de por qué no puede registrar. La causa puede ser la falta de permisos para escribir en el directorio log/.

Una de las razones más comunes de un error 500 es una caché obsoleta. Mientras que Nette actualiza la caché de forma inteligente y automática en modo desarrollo, en modo producción se centra en maximizar el rendimiento, y limpiar la caché después de cada modificación de código depende de ti. Intente borrar temp/cache.

Error 404, enrutamiento no funciona

Cuando todas las páginas (excepto la página de inicio) devuelven un error 404, parece un problema de configuración del servidor para URLs bonitas.

¿Cómo desactivar la caché durante el desarrollo?

Nette es inteligente, y no necesitas desactivar la caché en él. Durante el desarrollo, actualiza automáticamente la caché cada vez que hay un cambio en la plantilla o en la configuración del contenedor DI. Además, el modo de desarrollo se activa por auto-detección, por lo que normalmente no hay necesidad de configurar nada, o sólo la dirección IP.

A la hora de depurar el router, recomendamos desactivar la caché del navegador, donde, por ejemplo, podrían almacenarse las redirecciones: abre Herramientas de desarrollo (Ctrl+Mayús+I o Cmd+Opción+I) y, en el panel Red, marca la casilla para desactivar la caché.

Error #[\ReturnTypeWillChange] attribute should be used

Este error se produce si ha actualizado PHP a la versión 8.1 pero está utilizando Nette, que no es compatible con ella. Entonces la solución es actualizar Nette a una versión más reciente usando composer update. Nette es compatible con PHP 8.1 desde la versión 3.0. Si está usando una versión anterior (puede averiguarlo buscando en composer.json), actualice Nette o quédese con PHP 8.0.

Configuración de permisos de directorio

Si está desarrollando en macOS o Linux (o cualquier otro sistema basado en Unix), necesita configurar los privilegios de escritura en el servidor web. Suponiendo que su aplicación se encuentra en el directorio por defecto /var/www/html (Fedora, CentOS, RHEL)

cd /var/www/html/MY_PROJECT
chmod -R a+rw temp log

En algunos sistemas Linux (Fedora, CentOS, …) SELinux puede estar activado por defecto. Es posible que tenga que actualizar las políticas de SELinux o configurar las rutas de los directorios temp y log con el contexto de seguridad SELinux correcto. Los directorios temp y log deben configurarse con el contexto httpd_sys_rw_content_t; para el resto de la aplicación – principalmente la carpeta app – el contexto httpd_sys_content_t será suficiente. Ejecutar en el servidor como root:

semanage fcontext -at httpd_sys_rw_content_t '/var/www/html/MY_PROJECT/log(/.*)?'
semanage fcontext -at httpd_sys_rw_content_t '/var/www/html/MY_PROJECT/temp(/.*)?'
restorecon -Rv /var/www/html/MY_PROJECT/

A continuación, es necesario activar el booleano de SELinux httpd_can_network_connect_db para permitir que Nette se conecte a la base de datos a través de la red. Por defecto, está desactivado. El comando setsebool se puede utilizar para realizar esta tarea, y si se especifica la opción -P, esta configuración será persistente a través de reinicios.

setsebool -P httpd_can_network_connect_db on

¿Cómo cambiar o eliminar el directorio www de la URL?

El directorio www/ utilizado en los proyectos de ejemplo de Nette es el denominado directorio público o raíz documental del proyecto. Es el único directorio cuyo contenido es accesible para el navegador. Y contiene el archivo index.php, el punto de entrada que inicia una aplicación web escrita en Nette.

Para ejecutar la aplicación en el hosting, es necesario establecer el document-root a este directorio en la configuración del hosting. O, si el alojamiento tiene una carpeta pre-hecha para el directorio público con un nombre diferente (por ejemplo web, public_html etc.), simplemente renombre www/.

La solución no es impedir el acceso a todas las carpetas excepto www/ mediante reglas en el archivo .htaccess o en el router. Si tu alojamiento no permite establecer la raíz del documento en un subdirectorio (es decir, crear directorios un nivel por encima del directorio público), deberías buscar otro servicio de alojamiento. De lo contrario, te estarías exponiendo a importantes riesgos de seguridad. Sería como vivir en un apartamento donde la puerta principal no se puede cerrar y está siempre abierta de par en par.

¿Cómo configurar un servidor para URLs agradables?

Apache: debe activar y establecer reglas mod_rewrite en el archivo .htaccess:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule !\.(pdf|js|ico|gif|jpg|png|css|rar|zip|tar\.gz)$ index.php [L]

Si tiene problemas, asegúrese de que

Si está configurando la aplicación en una subcarpeta, es posible que tenga que descomentar la línea para la configuración de RewriteBase y establecerla en la carpeta correcta.

nginx: la directiva try_files debe utilizarse en la configuración del servidor:

location / {
	try_files $uri $uri/ /index.php$is_args$args;  # $is_args$args ¡ES IMPORTANTE!
}

El bloque location debe definirse exactamente una vez para cada ruta del sistema de ficheros en el bloque server. Si ya tiene un bloque location / en su configuración, añada la directiva try_files al bloque existente.

Compruebe si .htaccess funciona

La forma más sencilla de probar si Apache usa o ignora su fichero .htaccess, es romperlo intencionadamente. Ponga la línea Test al principio del archivo y ahora, si actualiza la página en su navegador, debería ver un Internal Server Error.

Si ve este error, ¡en realidad es bueno! Esto significa que Apache está analizando el archivo .htaccess, y encuentra el error que hemos puesto allí. Elimine la línea Test.

Si no ve un Error Interno del Servidor, su configuración de Apache ignora el fichero .htaccess. Generalmente, Apache lo ignora porque falta la directiva de configuración AllowOverride All.

Si lo aloja usted mismo, es bastante fácil de arreglar. Abra su httpd.conf o apache.conf en un editor de texto, localice la sección relevante y añada/cambie la directiva <Directory> y añada/cambie la directiva:

<Directory "/var/www/htdocs"> # path to your document root
    AllowOverride All
    ...

Si su sitio está alojado en otro lugar, compruebe su panel de control para ver si puede activar .htaccess allí. Si no es así, póngase en contacto con su proveedor de alojamiento para que lo haga por usted.

Compruebe si mod_rewrite está habilitado

Si ha comprobado que .htaccess funciona, puede verificar que la extensión mod_rewrite está habilitada. Ponga la línea RewriteEngine On al principio del archivo .htaccess y actualice la página en su navegador. Si ves un Internal Server Error, significa que mod_rewrite no está habilitado. Hay varias formas de activarlo. Consulte Stack Overflow para ver las distintas formas de hacerlo en diferentes configuraciones.

Nette genera enlaces con el mismo protocolo que utiliza la página actual. Así, en la página https://foo y viceversa. Si estás detrás de un proxy inverso que elimina HTTPS (por ejemplo, en Docker), entonces necesitas establecer un proxy en la configuración para que la detección de protocolo funcione correctamente.

Si usas Nginx como proxy, necesitas tener la redirección configurada así:

location / {
	proxy_set_header Host $host;
	proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
	proxy_set_header X-Forwarded-Proto $scheme;
	proxy_set_header X-Forwarded-Port  $server_port;
	proxy_pass http://IP-aplikace:80;  # IP o nombre de host del servidor/contenedor donde se ejecuta la aplicación
}

A continuación, debe especificar el proxy IP y, si procede, el rango IP de su red local donde ejecuta la infraestructura:

http:
	proxy: IP-proxy/IP-range

Uso de caracteres { } en JavaScript

Los caracteres { and } se utilizan para escribir etiquetas Latte. Todo (excepto el espacio y las comillas) después de { character is considered a tag. If you need to print character { (a menudo en JavaScript), puede poner un espacio (u otro carácter vacío) justo después de {. De esta manera se evita que se interprete como una etiqueta.

Si es necesario imprimir estos caracteres en una situación en la que se interpretarían como una etiqueta, puede utilizar etiquetas especiales para imprimir estos caracteres: {l} para { and {r} para }.

{is tag}
{ is not tag }
{l}is not tag{r}

Observe Presenter::getContext() is deprecated

Nette es de lejos el primer framework PHP que cambió a la inyección de dependencias y llevó a los programadores a usarla de forma consistente, empezando por los presentadores. Si un presentador necesita una dependencia, la pedirá. Por el contrario, la forma en que pasamos todo el contenedor DI a una clase y ésta extrae las dependencias de él directamente se considera un antipatrón (se llama localizador de servicios). Esta forma se utilizaba en Nette 0.x antes de la llegada de la inyección de dependencias, y su reliquia es el método Presenter::getContext(), hace tiempo marcado como obsoleto.

Si portas una aplicación Nette muy antigua, puedes encontrar que todavía utiliza este método. Así que desde la versión 3.1 de nette/application se encontrará con la advertencia Nette\Application\UI\Presenter::getContext() is deprecated, use dependency injection, desde la versión 4.0 se encontrará con el error de que el método no existe.

La solución limpia, por supuesto, es rediseñar la aplicación para pasar dependencias usando inyección de dependencias. Como solución alternativa, puede añadir su propio método getContext() a su presentador base y saltarse el mensaje:

abstract BasePresenter extends Nette\Application\UI\Presenter
{
	private Nette\DI\Container $context;

	public function injectContext(Nette\DI\Container $context)
	{
		$this->context = $context;
	}

	public function getContext(): Nette\DI\Container
	{
		return $this->context;
	}
}