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 una máquina de desarrollador, cambie al modo de desarrollador.

Si el mensaje de error contiene Tracy is unable to log error, averigüe por qué no se pueden registrar los errores. Puede hacerlo, por ejemplo, cambiando a modo desarrollador y llamando a Tracy\Debugger::log('hello'); después de $configurator->enableTracy(...). Tracy le dirá por qué no puede registrar. La causa suele ser la falta de permisos para escribir en el directorio log/.

Si la sentencia Tracy is unable to log error no aparece en el mensaje de error (ya no), puedes averiguar la razón del error en el log del directorio log/.

Una de las razones más comunes es una caché obsoleta. Mientras que Nette inteligentemente actualiza automáticamente la caché 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 #[\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 “deshacerse” de la carpeta www/ utilizando reglas en el archivo .htaccess o en el router. Si el alojamiento no te permite establecer document-root en un subdirectorio (es decir, crear directorios un nivel por encima del directorio público), busca otro. De lo contrario, estarías asumiendo un riesgo de seguridad importante. Sería como vivir en un apartamento en el que no puedes cerrar la puerta principal y siempre está abierta de par en par.

¿Cómo configurar un servidor para URLs agradables?

Apache: la extensión mod_rewrite debe estar permitida y configurada en un 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]

Para alterar la configuración de Apache con archivos .htaccess, la directiva AllowOverride debe estar habilitada. Este es el comportamiento por defecto de Apache.

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 is important
}

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.

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.

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;
	}
}