Solución de problemas
- Nette no funciona, aparece una página en blanco
- Error 500 Error del servidor: ¡Lo sentimos! …
- Error 404, enrutamiento no funciona
- Los cambios en las plantillas o en la configuración no se reflejan
- ¿Cómo desactivar la caché durante el desarrollo?
- Error #[\ReturnTypeWillChange] attribute should be used
- Configuración de permisos de directorio
- ¿Cómo cambiar o eliminar el directorio www de la URL?
- ¿Cómo configurar un servidor para URLs agradables?
- Compruebe si .htaccess funciona
- Compruebe si mod_rewrite está habilitado
- Los enlaces se generan sin https:
- Uso de caracteres { } en JavaScript
- Observe Presenter::getContext() is deprecated
Nette no funciona, aparece una página en blanco
- Pruebe a poner
ini_set('display_errors', '1'); error_reporting(E_ALL);
después dedeclare(strict_types=1);
en el archivoindex.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.
Los cambios en las plantillas o en la configuración no se reflejan
“He modificado la plantilla o la configuración, pero la web sigue mostrando la versión antigua”. Este comportamiento se produce en el modo de producción, que, por razones de rendimiento, no comprueba los cambios en los archivos y mantiene una caché generada previamente.
Para evitar 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('your.ip.address');
¿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
- el archivo
.htaccess
se encuentra en el directorio document-root (es decir, junto al archivoindex.php
) - Apache está procesando los archivos .htaccess
- mod_rewrite está activado
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.
Los enlaces se generan sin 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 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;
}
}