Bootstrap
Bootstrap es el código de arranque que inicializa el entorno, crea un contenedor de inyección de dependencias (DI) e inicia la aplicación. Vamos a discutir:
- cómo configurar su aplicación utilizando archivos NEON
- cómo manejar los modos de producción y desarrollo
- cómo crear el contenedor DI
Las aplicaciones, ya sean basadas en web o en scripts de línea de comandos, comienzan por algún tipo de inicialización del
entorno. En la antigüedad, podía ser un archivo llamado por ejemplo include.inc.php
el que se encargaba de esto, y
se incluía en el archivo inicial. En las aplicaciones Nette modernas, ha sido sustituido por la clase Bootstrap
, que
como parte de la aplicación se puede encontrar en el app/Bootstrap.php
. Por ejemplo, podría tener este aspecto:
use Nette\Bootstrap\Configurator;
class Bootstrap
{
private Configurator $configurator;
private string $rootDir;
public function __construct()
{
$this->rootDir = dirname(__DIR__);
// El configurador se encarga de configurar el entorno y los servicios de la aplicación.
$this->configurator = new Configurator;
// Establecer el directorio para los archivos temporales generados por Nette (por ejemplo, plantillas compiladas).
$this->configurator->setTempDirectory($this->rootDir . '/temp');
}
public function bootWebApplication(): Nette\DI\Container
{
$this->initializeEnvironment();
$this->setupContainer();
return $this->configurator->createContainer();
}
private function initializeEnvironment(): void
{
// Nette es inteligente, y el modo de desarrollo se activa automáticamente,
// o puede habilitarlo para una dirección IP específica descomentando la siguiente línea:
// $this->configurator->setDebugMode('secret@23.75.345.200');
// Habilita Tracy: la última herramienta de depuración "navaja suiza".
$this->configurator->enableTracy($this->rootDir . '/log');
// RobotLoader: carga automáticamente todas las clases en el directorio dado
$this->configurator->createRobotLoader()
->addDirectory(__DIR__)
->register();
}
private function setupContainer(): void
{
// Carga archivos de configuración
$this->configurator->addConfig($this->rootDir . '/config/common.neon');
}
}
index.php
El archivo inicial para aplicaciones web es index.php
, ubicado en el directorio público www/
.
Utiliza la clase Bootstrap
para inicializar el entorno y crear un contenedor DI. A continuación, obtiene el
servicio Application
del contenedor, que lanza la aplicación web:
$bootstrap = new App\Bootstrap;
// Inicializar el entorno + crear un contenedor DI
$container = $bootstrap->bootWebApplication();
// El contenedor DI crea un objeto Nette\Application\Application
$application = $container->getByType(Nette\Application\Application::class);
// Inicia la aplicación Nette y gestiona la petición entrante
$application->run();
Como puedes ver, la clase Nette\Bootstrap\Configurator, que ahora presentaremos con más detalle, ayuda a configurar el entorno y a crear un contenedor de inyección de dependencias (DI).
Modo Desarrollo vs Producción
Nette se comporta de forma diferente dependiendo de si se está ejecutando en un servidor de desarrollo o de producción:
- 🛠️ Modo Desarrollo
- Muestra la barra de depuración de Tracy con información útil (por ejemplo, consultas SQL, tiempo de ejecución, uso de memoria).
- Muestra una página de error detallada con trazas de llamadas a funciones y contenidos de variables cuando se produce un error.
- Actualiza automáticamente la caché cuando se modifican las plantillas Latte, los archivos de configuración, etc.
- Modo de producción
- No muestra ninguna información de depuración; se registran todos los errores.
- Muestra un
ErrorPresenter
o una página genérica de “Error de servidor” cuando se produce un error. - ¡La caché nunca se actualiza automáticamente!
- Optimizado para velocidad y seguridad.
El modo se determina automáticamente, por lo que en la mayoría de los casos no es necesario configurarlo o cambiarlo manualmente:
- Modo de desarrollo: Activo en localhost (dirección IP
127.0.0.1
o::1
) a menos que se esté utilizando un proxy (es decir, basándose en sus cabeceras HTTP). - Modo de producción: Activo en cualquier otro lugar.
Si desea habilitar el modo de desarrollo en otros casos, por ejemplo, para los programadores que acceden desde una dirección
IP específica, puede utilizar setDebugMode()
:
$this->configurator->setDebugMode('23.75.345.200'); // one or more IP addresses
Recomendamos encarecidamente combinar una dirección IP con una cookie. Almacenaremos un token secreto en la cookie
nette-debug
, por ejemplo secret1234
, y el modo de desarrollo se activará para los programadores con
esta combinación de IP y cookie.
$this->configurator->setDebugMode('secret1234@23.75.345.200');
También podemos desactivar completamente el modo de desarrollo, incluso para localhost:
$this->configurator->setDebugMode(false);
Nótese que el valor true
activa el modo desarrollador por fuerza, lo que nunca debería ocurrir en un servidor de
producción.
Herramienta de depuración Tracy
Para facilitar la depuración, activaremos la gran herramienta Tracy. En modo desarrollador visualiza los errores y en modo producción los registra en el directorio especificado:
$this->configurator->enableTracy($this->rootDir . '/log');
Archivos temporales
Nette utiliza la caché para el contenedor DI, RobotLoader, plantillas, etc. Por lo tanto es necesario establecer la ruta al directorio donde se almacenará la caché:
$this->configurator->setTempDirectory($this->rootDir . '/temp');
En Linux o macOS, establezca los permisos
de escritura para los directorios log/
y temp/
.
RobotLoader
Normalmente, querremos cargar automáticamente las clases usando RobotLoader, así que tenemos que iniciarlo y dejar que cargue las clases desde
el directorio donde se encuentra Bootstrap.php
(es decir, __DIR__
) y todos sus subdirectorios:
$this->configurator->createRobotLoader()
->addDirectory(__DIR__)
->register();
Una forma alternativa es utilizar únicamente la carga automática de Composer PSR-4.
Zona horaria
Configurator le permite especificar una zona horaria para su aplicación.
$this->configurator->setTimeZone('Europe/Prague');
Configuración del Contenedor DI
Parte del proceso de arranque es la creación de un contenedor DI, es decir, una fábrica de objetos, que es el corazón de toda la aplicación. En realidad es una clase PHP generada por Nette y almacenada en un directorio caché. La fábrica produce objetos clave de la aplicación y los archivos de configuración le indican cómo crearlos y configurarlos, y así influimos en el comportamiento de toda la aplicación.
Los ficheros de configuración suelen estar escritos en formato NEON. Puede leer lo que se puede configurar aquí.
En el modo de desarrollo, el contenedor se actualiza automáticamente cada vez que cambia el código o los archivos de configuración. En el modo de producción, se genera sólo una vez y los cambios en los archivos no se comprueban para maximizar el rendimiento.
Los archivos de configuración se cargan utilizando addConfig()
:
$this->configurator->addConfig($this->rootDir . '/config/common.neon');
El método addConfig()
se puede llamar varias veces para añadir varios archivos.
$configDir = $this->rootDir . '/config';
$this->configurator->addConfig($configDir . '/common.neon');
$this->configurator->addConfig($configDir . '/services.neon');
if (PHP_SAPI === 'cli') {
$this->configurator->addConfig($configDir . '/cli.php');
}
El nombre cli.php
no es una errata, la configuración también se puede escribir en un archivo PHP, que la
devuelve como un array.
Alternativamente, podemos utilizar la secciónincludes
para
cargar más archivos de configuración.
Si aparecen elementos con las mismas claves dentro de los archivos de configuración, se sobrescribirán o fusionarán en el caso de
los arrays. El fichero incluido más tarde tiene una prioridad mayor que el anterior. El fichero en el que aparece la sección
includes
tiene mayor prioridad que los ficheros incluidos en él.
Parámetros estáticos
Los parámetros utilizados en los archivos de configuración pueden definirse en la sección parameters
y
también pasarse (o sobrescribirse) por el método addStaticParameters()
(tiene el alias
addParameters()
). Es importante que los diferentes valores de los parámetros provoquen la generación de
contenedores DI adicionales, es decir, clases adicionales.
$this->configurator->addStaticParameters([
'projectId' => 23,
]);
En los archivos de configuración, podemos escribir la notación habitual %projectId%
para acceder al parámetro
denominado projectId
.
Parámetros dinámicos
También podemos añadir parámetros dinámicos al contenedor, sus diferentes valores, a diferencia de los parámetros estáticos, no provocarán la generación de nuevos contenedores DI.
$this->configurator->addDynamicParameters([
'remoteIp' => $_SERVER['REMOTE_ADDR'],
]);
Las variables de entorno podrían estar fácilmente disponibles utilizando parámetros dinámicos. Podemos acceder a ellas a
través de %env.variable%
en archivos de configuración.
$this->configurator->addDynamicParameters([
'env' => getenv(),
]);
Parámetros por defecto
Puede utilizar los siguientes parámetros estáticos en los archivos de configuración:
%appDir%
es la ruta absoluta al directorio del archivoBootstrap.php
%wwwDir%
es la ruta absoluta al directorio que contiene el archivo de entradaindex.php
%tempDir%
es la ruta absoluta al directorio para los archivos temporales%vendorDir%
es la ruta absoluta al directorio donde Composer instala las bibliotecas%rootDir%
es la ruta absoluta al directorio raíz del proyecto%debugMode%
indica si la aplicación está en modo depuración%consoleMode%
indica si la solicitud llegó a través de la línea de comandos
Servicios importados
Ahora vamos a profundizar más. Aunque el propósito de un contenedor DI es crear objetos, excepcionalmente puede existir la
necesidad de insertar un objeto existente en el contenedor. Esto lo hacemos definiendo el servicio con el atributo
imported: true
.
services:
myservice:
type: App\Model\MyCustomService
imported: true
Creamos una nueva instancia y la insertamos en bootstrap:
$this->configurator->addServices([
'myservice' => new App\Model\MyCustomService('foobar'),
]);
Diferentes entornos
No dude en personalizar la clase Bootstrap
según sus necesidades. Puedes añadir parámetros al método
bootWebApplication()
para diferenciar entre proyectos web. Alternativamente, puedes añadir otros métodos, como
bootTestEnvironment()
para inicializar el entorno para pruebas unitarias, bootConsoleApplication()
para
scripts llamados desde la línea de comandos, etc.
public function bootTestEnvironment(): Nette\DI\Container
{
Tester\Environment::setup(); // Inicialización del comprobador de redes
$this->setupContainer();
return $this->configurator->createContainer();
}
public function bootConsoleApplication(): Nette\DI\Container
{
$this->configurator->setDebugMode(false);
$this->initializeEnvironment();
$this->setupContainer();
return $this->configurator->createContainer();
}