Bootstrap
Bootstrap è il codice di avvio che inizializza l'ambiente, crea un contenitore di dependency injection (DI) e avvia l'applicazione. Discuteremo di:
- come configurare l'applicazione usando i file NEON
- come gestire le modalità di produzione e di sviluppo
- come creare il contenitore DI
Le applicazioni, siano esse basate sul web o su script a riga di comando, iniziano con una qualche forma di inizializzazione
dell'ambiente. In tempi antichi, poteva essere un file chiamato include.inc.php
a occuparsene, incluso nel file
iniziale. Nelle moderne applicazioni Nette, è stato sostituito dalla classe Bootstrap
, che come parte
dell'applicazione si trova nel file app/Bootstrap.php
. Ad esempio, potrebbe avere questo aspetto:
use Nette\Bootstrap\Configurator;
class Bootstrap
{
private Configurator $configurator;
private string $rootDir;
public function __construct()
{
$this->rootDir = dirname(__DIR__);
// Il configuratore è responsabile dell'impostazione dell'ambiente applicativo e dei servizi.
$this->configurator = new Configurator;
// Impostare la directory per i file temporanei generati da Nette (ad esempio, i modelli compilati).
$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 è intelligente e la modalità di sviluppo si attiva automaticamente,
// oppure si può attivare per un indirizzo IP specifico decommentando la seguente riga:
// $this->configurator->setDebugMode('secret@23.75.345.200');
// Abilita Tracy: lo strumento di debug per eccellenza, il "coltellino svizzero".
$this->configurator->enableTracy($this->rootDir . '/log');
// RobotLoader: carica automaticamente tutte le classi nella cartella data
$this->configurator->createRobotLoader()
->addDirectory(__DIR__)
->register();
}
private function setupContainer(): void
{
// Carica i file di configurazione
$this->configurator->addConfig($this->rootDir . '/config/common.neon');
}
}
index.php
Il file iniziale per le applicazioni web è index.php
, situato nella cartella pubblica www/
. Utilizza
la classe Bootstrap
per inizializzare l'ambiente e creare un contenitore DI. Quindi, ottiene il servizio
Application
dal contenitore, che lancia l'applicazione web:
$bootstrap = new App\Bootstrap;
// Inizializzare l'ambiente + creare un contenitore DI
$container = $bootstrap->bootWebApplication();
// Il contenitore DI crea un oggetto NetteApplicationApplication
$application = $container->getByType(Nette\Application\Application::class);
// Avviare l'applicazione Nette e gestire la richiesta in arrivo
$application->run();
Come si può notare, la classe Nette\Bootstrap\Configurator, che ora presenteremo in modo più dettagliato, aiuta a impostare l'ambiente e a creare un contenitore di dependency injection (DI).
Modalità di sviluppo e modalità di produzione
Nette distingue due modalità di base per l'esecuzione di una richiesta: sviluppo e produzione. La modalità di sviluppo è incentrata sul massimo comfort del programmatore, Tracy viene visualizzato, la cache viene aggiornata automaticamente quando si modificano i template o la configurazione del contenitore DI, ecc. La modalità di produzione è incentrata sulle prestazioni, Tracy registra solo gli errori e le modifiche dei modelli e di altri file non vengono controllate.
La selezione della modalità avviene tramite il rilevamento automatico, quindi di solito non è necessario configurare
o cambiare qualcosa manualmente. La modalità è di sviluppo se l'applicazione è in esecuzione su localhost (cioè l'indirizzo
IP 127.0.0.1
o ::1
) e non è presente alcun proxy (cioè la sua intestazione HTTP). Altrimenti, viene
eseguita in modalità di produzione.
Se si vuole abilitare la modalità di sviluppo in altri casi, ad esempio per i programmatori che accedono da un indirizzo IP
specifico, si può usare setDebugMode()
:
$this->configurator->setDebugMode('23.75.345.200'); // uno o più indirizzi IP
Consigliamo assolutamente di combinare un indirizzo IP con un cookie. Nel cookie nette-debug
verrà memorizzato un
token segreto, ad esempio secret1234
, e la modalità di sviluppo verrà attivata per i programmatori con questa
combinazione di IP e cookie.
$this->configurator->setDebugMode('secret1234@23.75.345.200');
Possiamo anche disattivare completamente la modalità sviluppatore, anche per localhost:
$this->configurator->setDebugMode(false);
Si noti che il valore true
attiva la modalità sviluppatore, cosa che non dovrebbe mai accadere su un server di
produzione.
Strumento di debug Tracy
Per facilitare il debug, attiviamo l'ottimo strumento Tracy. In modalità sviluppatore visualizza gli errori e in modalità produzione li registra nella directory specificata:
$this->configurator->enableTracy($this->rootDir . '/log');
File temporanei
Nette utilizza la cache per il contenitore DI, il RobotLoader, i modelli, ecc. Per questo motivo è necessario impostare il percorso della cartella in cui verrà memorizzata la cache:
$this->configurator->setTempDirectory($this->rootDir . '/temp');
Su Linux o macOS, impostare i permessi
di scrittura per le directory log/
e temp/
.
RobotLoader
Di solito, vogliamo caricare automaticamente le classi usando RobotLoader,
quindi dobbiamo avviarlo e fargli caricare le classi dalla directory in cui si trova Bootstrap.php
(cioè
__DIR__
) e da tutte le sue sottodirectory:
$this->configurator->createRobotLoader()
->addDirectory(__DIR__)
->register();
Un modo alternativo è quello di utilizzare solo il caricamento automatico di Composer PSR-4.
Fuso orario
Il configuratore consente di specificare un fuso orario per l'applicazione.
$this->configurator->setTimeZone('Europe/Prague');
Configurazione del contenitore DI
Parte del processo di avvio è la creazione di un contenitore DI, cioè una fabbrica di oggetti, che è il cuore dell'intera applicazione. Si tratta in realtà di una classe PHP generata da Nette e memorizzata in una cartella cache. Il factory produce gli oggetti chiave dell'applicazione e i file di configurazione gli indicano come crearli e configurarli, influenzando così il comportamento dell'intera applicazione.
I file di configurazione sono solitamente scritti nel formato NEON. Qui si può leggere cosa si può configurare.
In modalità di sviluppo, il contenitore viene aggiornato automaticamente ogni volta che si modifica il codice o i file di configurazione. In modalità di produzione, viene generato solo una volta e le modifiche ai file non vengono controllate per massimizzare le prestazioni.
I file di configurazione vengono caricati usando addConfig()
:
$this->configurator->addConfig($this->rootDir . '/config/common.neon');
Il metodo addConfig()
può essere richiamato più volte per aggiungere più file.
$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');
}
Il nome cli.php
non è un refuso, la configurazione può anche essere scritta in un file PHP, che la restituisce
come array.
In alternativa, si può usare la sezioneincludes
per
caricare altri file di configurazione.
Se all'interno dei file di configurazione compaiono elementi con le stesse chiavi, questi verranno sovrascritti o uniti nel caso di array. Il
file incluso successivamente ha una priorità maggiore rispetto al precedente. Il file in cui è elencata la sezione
includes
ha una priorità più alta dei file in esso inclusi.
Parametri statici
I parametri usati nei file di configurazione possono essere definiti nella sezione parameters
e
anche passati (o sovrascritti) dal metodo addStaticParameters()
(ha l'alias addParameters()
). È
importante che valori diversi dei parametri causino la generazione di contenitori DI aggiuntivi, cioè di classi aggiuntive.
$this->configurator->addStaticParameters([
'projectId' => 23,
]);
Nei file di configurazione, possiamo scrivere la solita notazione %projectId%
per accedere al parametro chiamato
projectId
.
Parametri dinamici
Possiamo anche aggiungere parametri dinamici al contenitore; i loro diversi valori, a differenza dei parametri statici, non causeranno la generazione di nuovi contenitori DI.
$this->configurator->addDynamicParameters([
'remoteIp' => $_SERVER['REMOTE_ADDR'],
]);
Le variabili d'ambiente possono essere facilmente rese disponibili usando parametri dinamici. Possiamo accedervi tramite
%env.variable%
nei file di configurazione.
$this->configurator->addDynamicParameters([
'env' => getenv(),
]);
Parametri predefiniti
È possibile utilizzare i seguenti parametri statici nei file di configurazione:
%appDir%
è il percorso assoluto della directory del fileBootstrap.php
%wwwDir%
è il percorso assoluto della directory contenente il file di ingressoindex.php
%tempDir%
è il percorso assoluto della directory per i file temporanei%vendorDir%
è il percorso assoluto della directory in cui Composer installa le librerie%rootDir%
è il percorso assoluto della directory principale del progetto%debugMode%
indica se l'applicazione è in modalità debug%consoleMode%
indica se la richiesta è arrivata attraverso la riga di comando
Servizi importati
Ora stiamo andando più a fondo. Sebbene lo scopo di un contenitore DI sia quello di creare oggetti, eccezionalmente può
essere necessario inserire un oggetto esistente nel contenitore. Lo facciamo definendo il servizio con l'attributo
imported: true
.
services:
myservice:
type: App\Model\MyCustomService
imported: true
Creare una nuova istanza e inserirla in bootstrap:
$this->configurator->addServices([
'myservice' => new App\Model\MyCustomService('foobar'),
]);
Ambienti diversi
Non esitate a personalizzare la classe Bootstrap
in base alle vostre esigenze. Si possono aggiungere parametri al
metodo bootWebApplication()
per differenziare i progetti web. In alternativa, si possono aggiungere altri metodi,
come bootTestEnvironment()
per inizializzare l'ambiente per i test unitari, bootConsoleApplication()
per gli script chiamati dalla riga di comando e così via.
public function bootTestEnvironment(): Nette\DI\Container
{
Tester\Environment::setup(); // Inizializzazione del tester Nette
$this->setupContainer();
return $this->configurator->createContainer();
}
public function bootConsoleApplication(): Nette\DI\Container
{
$this->configurator->setDebugMode(false);
$this->initializeEnvironment();
$this->setupContainer();
return $this->configurator->createContainer();
}