Solución de problemas

Nette no funciona, se muestra una página en blanco

  • Intente insertar ini_set('display_errors', '1'); error_reporting(E_ALL); en el archivo index.php justo después de declare(strict_types=1);, esto forzará la visualización de errores.
  • Si sigue viendo una pantalla en blanco, probablemente haya un error en la configuración del servidor y la razón se revelará en el registro del servidor. Por si acaso, verifique si PHP funciona en absoluto intentando imprimir algo usando echo 'test';
  • Si ve el error Server Error: We're sorry! …, continúe con la siguiente sección:

Error 500 Server Error: We're sorry! …

Esta página de error la muestra Nette en modo de producción. Si se le muestra en su computadora de desarrollo, cambie al modo de desarrollo y se le mostrará Tracy con un mensaje detallado.

La razón del error siempre se puede encontrar en el registro en el directorio log/. Sin embargo, si el mensaje de error muestra la frase Tracy is unable to log error, primero averigüe por qué no se pueden registrar los errores. Puede hacerlo, por ejemplo, cambiando temporalmente al modo de desarrollo y dejando que Tracy registre cualquier cosa después de su inicio:

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

Tracy le dirá por qué no puede registrar. La causa puede ser un componente defectuoso, pero más probablemente permisos insuficientes para escribir en el directorio log/.

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

Error 404, el enrutamiento no funciona

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

Los cambios en las plantillas o la configuración no se reflejan

“He modificado la plantilla o la configuración, pero el sitio web sigue mostrando la versión antigua.” Este comportamiento ocurre en el modo de producción, que por razones de rendimiento no verifica los cambios en los archivos y mantiene la caché generada una vez.

Para no tener que borrar manualmente la caché en el servidor de producción después de cada modificación, habilite el modo de desarrollo para su dirección IP en el archivo Bootstrap.php:

$this->configurator->setDebugMode('su.direccion.ip');

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

Nette es inteligente y no necesita desactivar el almacenamiento en caché. Durante el desarrollo, actualiza automáticamente la caché cada vez que se cambia una plantilla o la configuración del contenedor DI. Además, el modo de desarrollo se activa por autodetección, por lo que generalmente no es necesario configurar nada, o solo la dirección IP.

Al depurar el router, recomendamos desactivar la caché en el navegador, donde pueden almacenarse, por ejemplo, redirecciones: abra las Herramientas de desarrollo (Ctrl+Shift+I o Cmd+Option+I) y en el panel Red (Network) marque la desactivación de la caché.

Error #[\ReturnTypeWillChange] attribute should be used

Este error aparece si ha actualizado PHP a la versión 8.1, pero está utilizando una versión de Nette que no es compatible con ella. La solución es, por lo tanto, 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á utilizando una versión anterior (compruébelo 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), deberá configurar los permisos de escritura para el servidor web. Supongamos que su aplicación se encuentra en el directorio predeterminado /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 está habilitado de forma predeterminada. Deberá ajustar las políticas de SELinux en consecuencia y establecer el contexto de seguridad SELinux correcto para las carpetas temp y log. Para temp y log estableceremos el tipo de contexto httpd_sys_rw_content_t, para el resto de la aplicación (y especialmente para la carpeta app) será suficiente httpd_sys_content_t. Ejecute en el servidor:

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/

Además, es necesario habilitar el booleano de SELinux httpd_can_network_connect_db, que está desactivado por defecto y que permite a Nette conectarse a la base de datos a través de la red. Usaremos el comando setsebool y con la opción -P haremos el cambio permanente, es decir, después de reiniciar el servidor no nos encontraremos con una sorpresa desagradable:

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 en Nette representa el llamado directorio público o document-root 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 la aplicación web escrita en Nette.

Para poner en funcionamiento la aplicación en un hosting, es necesario tener configurado correctamente el document-root. Tiene dos opciones:

  1. Establecer el document-root en este directorio en la configuración del hosting.
  2. Si el hosting tiene una carpeta predefinida (por ejemplo, public_html), renombre www/ a este nombre.

Nunca intente resolver la seguridad solo con .htaccess o el router, que impedirían el acceso a otras carpetas.

Si el hosting no permitiera establecer el document-root en un subdirectorio (es decir, crear directorios un nivel por encima del directorio público), busque otro. De lo contrario, correría un riesgo de seguridad considerable. Sería como vivir en un apartamento donde la puerta de entrada no se puede cerrar y siempre está abierta.

¿Cómo configurar el servidor para URLs amigables?

Apache: es necesario habilitar y configurar las reglas de 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 encuentra problemas, asegúrese de que:

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

nginx: es necesario configurar la redirección usando la directiva try_files dentro del bloque location / en la configuración del servidor.

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

El bloque location para cada ruta del sistema de archivos solo puede aparecer una vez en el bloque server. Si ya tiene location / en la configuración, agregue la directiva try_files a él.

Verificación de que .htaccess funciona

La forma más sencilla de probar si Apache usa o ignora su archivo .htaccess es dañarlo intencionalmente. Inserte la línea Test al principio del archivo y ahora, si actualiza la página en el navegador, debería ver Internal Server Error.

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

Si no aparece Internal Server Error, su configuración de Apache está ignorando el archivo .htaccess. Generalmente, Apache lo ignora debido a la falta de la directiva de configuración AllowOverride All.

Si lo aloja usted mismo, se puede arreglar fácilmente. Abra el archivo httpd.conf o apache.conf en un editor de texto, busque la sección <Directory> correspondiente y agregue/cambie esta directiva:

<Directory "/var/www/htdocs"> # ruta a su document root
    AllowOverride All
    ...

Si su sitio web está alojado en otro lugar, consulte el panel de control para ver si puede habilitar el archivo .htaccess allí. Si no, póngase en contacto con su proveedor de hosting para que lo haga por usted.

Verificación de que mod_rewrite está habilitado

Si ha verificado que .htaccess funciona, puede verificar si la extensión mod_rewrite está habilitada. Inserte la línea RewriteEngine On al principio del archivo .htaccess y actualice la página en el navegador. Si aparece Internal Server Error, significa que mod_rewrite no está habilitado. Hay varias formas de habilitarlo. Puede encontrar diferentes formas de hacerlo en diversas configuraciones en Stack Overflow.

Los enlaces se generan sin https:

Nette genera enlaces con el mismo protocolo que tiene la propia página. Es decir, en la página https://foo genera enlaces que comienzan con https: y viceversa. Si está detrás de un servidor proxy inverso que elimina HTTPS (por ejemplo, en Docker), entonces es necesario configurar el proxy en la configuración para que la detección del protocolo funcione correctamente.

Si utiliza Nginx como proxy, es necesario tener configurada la redirección, por ejemplo, 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-aplicacion:80;  # IP o hostname del servidor/contenedor donde se ejecuta la aplicación
}

Además, es necesario indicar en la configuración la IP del proxy y, opcionalmente, el rango de IP de su red local donde opera la infraestructura:

http:
	proxy: IP-proxy/IP-range

Uso de los caracteres { } en JavaScript

Los caracteres { y } se utilizan para escribir etiquetas Latte. Se considera una etiqueta cualquier cosa que siga al carácter { con la excepción de un espacio y una comilla. Por lo tanto, si necesita imprimir directamente el carácter { (a menudo, por ejemplo, en JavaScript), puede poner un espacio (u otro carácter en blanco) después del carácter {. De esta manera evitará la traducción como etiqueta.

Si es necesario imprimir estos caracteres en una situación en la que el texto se entendería como una etiqueta, puede utilizar etiquetas especiales para imprimir estos caracteres: {l} para { y {r} para }.

{es una etiqueta}
{ no es una etiqueta }
{l}no es una etiqueta{r}

Mensaje Presenter::getContext() is deprecated

Nette es, con mucho, el primer framework PHP que pasó a la inyección de dependencia y guió a los programadores a usarla consistentemente, desde los propios presenters. Si un presenter necesita alguna dependencia, la solicita. Por el contrario, la forma en que pasamos todo el contenedor DI a la clase, y esta extrae las dependencias directamente de él, se considera un antipatrón (se llama localizador de servicios). Este método se usaba en Nette 0.x antes de la llegada de la inyección de dependencia y su remanente es el método Presenter::getContext(), marcado como obsoleto hace mucho tiempo.

Si está portando una aplicación muy antigua para Nette, puede que todavía use este método. 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 con el error de que el método no existe.

La solución limpia es, por supuesto, rediseñar la aplicación para que pase las dependencias usando la inyección de dependencia. Como solución alternativa, puede agregar su propio método getContext() a su presenter base y así evitar 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;
	}
}
versión: 4.0