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
{
	public static function boot(): Configurator
	{
		$appDir = dirname(__DIR__);
		$configurator = new Configurator;
		//$configurator->setDebugMode('secret@23.75.345.200');
		$configurator->enableTracy($appDir . '/log');
		$configurator->setTempDirectory($appDir . '/temp');
		$configurator->createRobotLoader()
			->addDirectory(__DIR__)
			->register();
		$configurator->addConfig($appDir . '/config/common.neon');
		return $configurator;
	}
}

index.php

En el caso de las aplicaciones web, el archivo inicial es index.php, que se encuentra en el directorio público www/. Permite a la clase Bootstrap inicializar el entorno y devolver el $configurator que crea el contenedor DI. Luego obtiene el servicio Application, que ejecuta la aplicación web:

// initialize the environment + get Configurator object
$configurator = App\Bootstrap::boot();
// create a DI container
$container = $configurator->createContainer();
// DI container creates a Nette\Application\Application object
$application = $container->getByType(Nette\Application\Application::class);
// start Nette application
$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 distingue entre dos modos básicos en los que se ejecuta una petición: desarrollo y producción. El modo de desarrollo está enfocado a la máxima comodidad del programador, se visualiza Tracy, la caché se actualiza automáticamente al cambiar las plantillas o la configuración del contenedor DI, etc. El modo de producción está enfocado al rendimiento, Tracy sólo registra los errores y no se comprueban los cambios de plantillas y otros ficheros.

La selección del modo se hace por autodetección, por lo que normalmente no hay necesidad de configurar o cambiar nada manualmente. El modo es desarrollo si la aplicación se ejecuta en localhost (es decir, la dirección IP 127.0.0.1 o ::1) y no hay proxy presente (es decir, su cabecera HTTP). De lo contrario, se ejecuta en modo de producción.

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():

$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.

$configurator->setDebugMode('secret1234@23.75.345.200');

También podemos desactivar completamente el modo de desarrollo, incluso para localhost:

$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:

$configurator->enableTracy($appDir . '/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é:

$configurator->setTempDirectory($appDir . '/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:

$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.

$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():

$configurator->addConfig($appDir . '/config/common.neon');

El método addConfig() se puede llamar varias veces para añadir varios archivos.

$configurator->addConfig($appDir . '/config/common.neon');
$configurator->addConfig($appDir . '/config/services.neon');
if (PHP_SAPI === 'cli') {
	$configurator->addConfig($appDir . '/config/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.

$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.

$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.

$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 archivo Bootstrap.php
  • %wwwDir% es la ruta absoluta al directorio que contiene el archivo de entrada index.php
  • %tempDir% es la ruta absoluta al directorio para los archivos temporales
  • %vendorDir% es la ruta absoluta al directorio donde Composer instala las bibliotecas
  • %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:

$configurator->addServices([
	'myservice' => new App\Model\MyCustomService('foobar'),
]);

Diferentes entornos

Siéntete libre de personalizar la clase Bootstrap para adaptarla a tus necesidades. Puedes añadir parámetros al método boot() para diferenciar proyectos web, o añadir otros métodos, como bootForTests(), que inicializa el entorno para pruebas unitarias, bootForCli() para scripts llamados desde la línea de comandos, etc.

public static function bootForTests(): Configurator
{
	$configurator = self::boot();
	Tester\Environment::setup(); // Nette Tester initialization
	return $configurator;
}
versión: 4.0