Bootstrap
Bootstrap ist ein Bootcode, der die Umgebung initialisiert, einen Dependency Injection (DI) Container erstellt und die Anwendung startet. Wir werden das besprechen:
- wie Sie Ihre Anwendung mithilfe von NEON-Dateien konfigurieren
- wie man den Produktions- und den Entwicklungsmodus handhabt
- wie man den DI-Container erstellt
Anwendungen, ob webbasiert oder als Befehlszeilenskript, beginnen mit einer Art Initialisierung der Umgebung. In früheren
Zeiten konnte das eine Datei namens include.inc.php
sein, die dafür zuständig war und in der Startdatei enthalten
war. In modernen Nette-Anwendungen wurde sie durch die Klasse Bootstrap
ersetzt, die als Teil der Anwendung in der
Datei app/Bootstrap.php
zu finden ist. Sie könnte zum Beispiel so aussehen:
use Nette\Bootstrap\Configurator;
class Bootstrap
{
private Configurator $configurator;
private string $rootDir;
public function __construct()
{
$this->rootDir = dirname(__DIR__);
// Der Konfigurator ist für das Einrichten der Anwendungsumgebung und der Dienste zuständig.
$this->configurator = new Configurator;
// Legen Sie das Verzeichnis für temporäre Dateien fest, die von Nette erzeugt werden (z. B. kompilierte Vorlagen)
$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 ist intelligent, und der Entwicklungsmodus wird automatisch aktiviert,
// oder Sie können ihn für eine bestimmte IP-Adresse aktivieren, indem Sie die folgende Zeile auskommentieren:
// $this->configurator->setDebugMode('secret@23.75.345.200');
// Aktiviert Tracy: das ultimative "Schweizer Taschenmesser" zur Fehlersuche.
$this->configurator->enableTracy($this->rootDir . '/log');
// RobotLoader: Lädt automatisch alle Klassen im angegebenen Verzeichnis
$this->configurator->createRobotLoader()
->addDirectory(__DIR__)
->register();
}
private function setupContainer(): void
{
// Konfigurationsdateien laden
$this->configurator->addConfig($this->rootDir . '/config/common.neon');
}
}
index.php
Die Ausgangsdatei für Webanwendungen ist index.php
, die sich im öffentlichen Verzeichnis www/
befindet. Sie verwendet die Klasse Bootstrap
, um die Umgebung zu initialisieren und einen DI-Container zu erstellen.
Anschließend wird der Dienst Application
aus dem Container abgerufen, der die Webanwendung startet:
$bootstrap = new App\Bootstrap;
// Initialisierung der Umgebung + Erstellung eines DI-Containers
$container = $bootstrap->bootWebApplication();
// DI-Container erstellt ein Nette\Anwendung\Anwendungsobjekt
$application = $container->getByType(Nette\Application\Application::class);
// Starten Sie die Nette-Anwendung und bearbeiten Sie die eingehende Anfrage
$application->run();
Wie Sie sehen, hilft die Klasse Nette\Bootstrap\Configurator, die wir nun genauer vorstellen werden, bei der Einrichtung der Umgebung und der Erstellung eines Dependency-Injection-Containers (DI).
Entwicklungs- vs. Produktionsmodus
Nette verhält sich unterschiedlich, je nachdem, ob es auf einem Entwicklungs- oder Produktionsserver ausgeführt wird:
- 🛠️ Entwicklungsmodus
- Zeigt die Tracy-Debug-Leiste mit nützlichen Informationen an (z. B. SQL-Abfragen, Ausführungszeit, Speicherverbrauch).
- Zeigt eine detaillierte Fehlerseite mit Funktionsaufrufspuren und Variableninhalten, wenn ein Fehler auftritt.
- Aktualisiert automatisch den Cache, wenn Latte-Vorlagen, Konfigurationsdateien usw. geändert werden.
- 🚀 Produktionsmodus
- Es werden keine Debugging-Informationen angezeigt; alle Fehler werden protokolliert.
- Zeigt eine
ErrorPresenter
oder eine allgemeine „Server Error“-Seite an, wenn ein Fehler auftritt. - Der Cache wird nie automatisch aktualisiert!
- Optimiert für Geschwindigkeit und Sicherheit.
Der Modus wird automatisch bestimmt, so dass es in den meisten Fällen nicht notwendig ist, ihn manuell zu konfigurieren oder zu wechseln:
- Entwicklungsmodus: Aktiv auf localhost (IP-Adresse
127.0.0.1
oder::1
), es sei denn, es wird ein Proxy verwendet (d. h. basierend auf den HTTP-Headern). - Produktionsmodus: Überall sonst aktiv.
Wenn Sie den Entwicklungsmodus in anderen Fällen aktivieren möchten, z. B. für Programmierer, die von einer bestimmten
IP-Adresse aus zugreifen, können Sie setDebugMode()
verwenden:
$this->configurator->setDebugMode('23.75.345.200'); // eine oder mehrere IP-Adressen
Wir empfehlen auf jeden Fall, eine IP-Adresse mit einem Cookie zu kombinieren. Wir speichern ein geheimes Token im
nette-debug
Cookie, z.B. secret1234
, und der Entwicklungsmodus wird für Programmierer mit dieser
Kombination von IP und Cookie aktiviert.
$this->configurator->setDebugMode('secret1234@23.75.345.200');
Wir können den Entwicklermodus auch komplett abschalten, sogar für localhost:
$this->configurator->setDebugMode(false);
Beachten Sie, dass der Wert true
den Entwicklermodus standardmäßig einschaltet, was auf einem Produktionsserver
niemals passieren sollte.
Debugging-Werkzeug Tracy
Zur einfachen Fehlersuche werden wir das großartige Tool Tracy einschalten. Im Entwicklermodus zeigt es Fehler an und im Produktionsmodus protokolliert es Fehler in das angegebene Verzeichnis:
$this->configurator->enableTracy($this->rootDir . '/log');
Temporäre Dateien
Nette verwendet den Cache für DI-Container, RobotLoader, Vorlagen usw. Daher ist es notwendig, den Pfad zu dem Verzeichnis festzulegen, in dem der Cache gespeichert werden soll:
$this->configurator->setTempDirectory($this->rootDir . '/temp');
Unter Linux oder macOS setzen Sie die Schreibrechte für die Verzeichnisse
log/
und temp/
.
RobotLoader
Normalerweise wollen wir die Klassen automatisch mit RobotLoader laden, also müssen wir ihn
starten und ihn Klassen aus dem Verzeichnis laden lassen, in dem sich Bootstrap.php
befindet (d.h.
__DIR__
) und aus allen seinen Unterverzeichnissen:
$this->configurator->createRobotLoader()
->addDirectory(__DIR__)
->register();
Eine alternative Möglichkeit ist, nur das automatische Laden von Composer PSR-4 zu verwenden.
Zeitzone
Configurator ermöglicht es Ihnen, eine Zeitzone für Ihre Anwendung festzulegen.
$this->configurator->setTimeZone('Europe/Prague');
DI-Container-Konfiguration
Teil des Boot-Prozesses ist die Erstellung eines DI-Containers, d.h. einer Fabrik für Objekte, die das Herzstück der gesamten Anwendung ist. Dabei handelt es sich um eine PHP-Klasse, die von Nette generiert und in einem Cache-Verzeichnis gespeichert wird. Die Factory erzeugt wichtige Anwendungsobjekte, und Konfigurationsdateien weisen sie an, wie sie zu erstellen und zu konfigurieren sind, wodurch wir das Verhalten der gesamten Anwendung beeinflussen.
Konfigurationsdateien werden normalerweise im NEON-Format geschrieben. Was konfiguriert werden kann, können Sie hier nachlesen.
Im Entwicklungsmodus wird der Container jedes Mal automatisch aktualisiert, wenn Sie den Code oder die Konfigurationsdateien ändern. Im Produktionsmodus wird er nur einmal generiert und Dateiänderungen werden nicht überprüft, um die Leistung zu maximieren.
Konfigurationsdateien werden mit addConfig()
geladen:
$this->configurator->addConfig($this->rootDir . '/config/common.neon');
Die Methode addConfig()
kann mehrfach aufgerufen werden, um mehrere Dateien hinzuzufügen.
$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');
}
Der Name cli.php
ist kein Tippfehler, die Konfiguration kann auch in eine PHP-Datei geschrieben werden, die sie
als Array zurückgibt.
Alternativ können wir auch den Abschnittincludes
verwenden, um weitere
Konfigurationsdateien zu laden.
Wenn Elemente mit denselben Schlüsseln in Konfigurationsdateien vorkommen, werden sie überschrieben oder im Falle von Arrays zusammengeführt. Die später eingebundene Datei hat eine höhere
Priorität als die vorherige. Die Datei, in der der Abschnitt includes
aufgeführt ist, hat eine höhere Priorität
als die in ihr enthaltenen Dateien.
Statische Parameter
Parameter, die in Konfigurationsdateien verwendet werden, können im Abschnitt parameters
definiert und auch von der
Methode addStaticParameters()
übergeben (oder überschrieben) werden (sie hat den Alias
addParameters()
). Wichtig ist, dass unterschiedliche Parameterwerte die Erzeugung zusätzlicher DI-Container, d.h.
zusätzlicher Klassen, bewirken.
$this->configurator->addStaticParameters([
'projectId' => 23,
]);
In Konfigurationsdateien können wir die übliche Notation %projectId%
verwenden, um auf den Parameter
projectId
zuzugreifen.
Dynamische Parameter
Wir können dem Container auch dynamische Parameter hinzufügen, deren unterschiedliche Werte, im Gegensatz zu statischen Parametern, nicht die Erzeugung neuer DI-Container verursachen.
$this->configurator->addDynamicParameters([
'remoteIp' => $_SERVER['REMOTE_ADDR'],
]);
Umgebungsvariablen können mit dynamischen Parametern leicht verfügbar gemacht werden. Wir können über
%env.variable%
in Konfigurationsdateien auf sie zugreifen.
$this->configurator->addDynamicParameters([
'env' => getenv(),
]);
Standard-Parameter
Sie können die folgenden statischen Parameter in den Konfigurationsdateien verwenden:
%appDir%
ist der absolute Pfad zu dem Verzeichnis, in dem sich die DateiBootstrap.php
befindet%wwwDir%
ist der absolute Pfad zu dem Verzeichnis, das dieindex.php
Eintragsdatei enthält%tempDir%
ist der absolute Pfad zu dem Verzeichnis für temporäre Dateien%vendorDir%
ist der absolute Pfad zu dem Verzeichnis, in dem Composer die Bibliotheken installiert%rootDir%
ist der absolute Pfad zum Stammverzeichnis des Projekts%debugMode%
gibt an, ob sich die Anwendung im Debug-Modus befindet%consoleMode%
zeigt an, ob die Anfrage über die Befehlszeile kam
Importierte Dienste
Wir gehen jetzt in die Tiefe. Obwohl der Zweck eines DI-Containers darin besteht, Objekte zu erstellen, kann es in
Ausnahmefällen erforderlich sein, ein vorhandenes Objekt in den Container einzufügen. Wir tun dies, indem wir den Dienst mit dem
Attribut imported: true
definieren.
services:
myservice:
type: App\Model\MyCustomService
imported: true
Erstellen Sie eine neue Instanz und fügen Sie sie in Bootstrap ein:
$this->configurator->addServices([
'myservice' => new App\Model\MyCustomService('foobar'),
]);
Verschiedene Umgebungen
Zögern Sie nicht, die Klasse Bootstrap
nach Ihren Bedürfnissen anzupassen. Sie können der Methode
bootWebApplication()
Parameter hinzufügen, um zwischen Webprojekten zu unterscheiden. Alternativ können Sie auch
andere Methoden hinzufügen, z. B. bootTestEnvironment()
, um die Umgebung für Unit-Tests zu initialisieren,
bootConsoleApplication()
für Skripte, die von der Befehlszeile aus aufgerufen werden, und so weiter.
public function bootTestEnvironment(): Nette\DI\Container
{
Tester\Environment::setup(); // Initialisierung des Nette-Testers
$this->setupContainer();
return $this->configurator->createContainer();
}
public function bootConsoleApplication(): Nette\DI\Container
{
$this->configurator->setDebugMode(false);
$this->initializeEnvironment();
$this->setupContainer();
return $this->configurator->createContainer();
}