Heim  >  Artikel  >  PHP-Framework  >  ThinkPHP6-Anwendungsinitialisierung (Quellcode-Analyse)

ThinkPHP6-Anwendungsinitialisierung (Quellcode-Analyse)

藏色散人
藏色散人nach vorne
2020-01-30 19:29:363928Durchsuche

ThinkPHP6-Anwendungsinitialisierung (Quellcode-Analyse)

ThinkPHP6-Quellcode-Analyse-Anwendungsinitialisierung

App Construct

Werfen wir zunächst einen Blick darauf, was in __construct getan wird. Grundsätzlich führt jedes Framework hier einige grundlegende Operationen aus, das heißt, es erweitert sich von hier aus.

public function __construct(string $rootPath = '')
{
    $this->thinkPath   = dirname(__DIR__) . DIRECTORY_SEPARATOR;
    $this->rootPath    = $rootPath ? rtrim($rootPath, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR : $this->getDefaultRootPath();
    $this->appPath     = $this->rootPath . 'app' . DIRECTORY_SEPARATOR;
    $this->runtimePath = $this->rootPath . 'runtime' . DIRECTORY_SEPARATOR;
    if (is_file($this->appPath . 'provider.php')) {
        $this->bind(include $this->appPath . 'provider.php');
    }
    static::setInstance($this);
    $this->instance('app', $this);
    $this->instance('think\Container', $this);
}

● Dem Parameter rootPath der Magic-Methode nach zu urteilen, unterstützt sie die Anpassung des Stammverzeichnispfads.

● Richten Sie thinkPath, rootPath, appPath, runtimePath ein.

● Binden Sie den Standarddienstanbieter und stellen Sie insgesamt zwei bereit: appReques und appExceptionHandle. Gehen Sie insbesondere zu appPath, um anzuzeigen

● Legen Sie die aktuelle Containerinstanz APP fest

● Binden Sie die App($this)-Instanz an den Container, bei dem es sich um app bzw. thinkContainer handelt

Hier müssen Sie aufpassen. Die App-Klasse erbt den Container und bindet daher ihre eigene Instanz an den Container.

Es scheint, dass die gesamte Anwendung hier initialisiert wurde? Hier muss ich einen Teil des Inhalts der Anforderungsausführung einfügen, da dies die Hauptinitialisierungsarbeit des Frameworks ist. Ich halte es nicht für sinnvoll, diesen Teil der Initialisierungsarbeit in die Anforderungsausführung zu integrieren.

Hauptinitialisierung

public function initialize()
{
    $this->initialized = true;
    $this->beginTime = microtime(true);
    $this->beginMem  = memory_get_usage();
    // 加载环境变量
    if (is_file($this->rootPath . '.env')) {
        $this->env->load($this->rootPath . '.env');
    }
    $this->configExt = $this->env->get('config_ext', '.php');
    $this->debugModeInit();
    // 加载全局初始化文件
    $this->load();
    // 加载框架默认语言包
    $langSet = $this->lang->defaultLangSet();
    $this->lang->load($this->thinkPath . 'lang' . DIRECTORY_SEPARATOR . $langSet . '.php');
    // 加载应用默认语言包
    $this->loadLangPack($langSet);
    // 监听AppInit
    $this->event->trigger('AppInit');
    date_default_timezone_set($this->config->get('app.default_timezone', 'Asia/Shanghai'));
    // 初始化
    foreach ($this->initializers as $initializer) {
        $this->make($initializer)->init($this);
    }
    return $this;
}

● .env-Umgebungsvariablendatei laden

● Konfigurationsdateien und Dateien innerhalb der Anwendung laden

● Laden Sie common.php in die Anwendung

● Laden Sie die Hilfsfunktion in helper.php im thinkPath-Verzeichnis

● Laden Sie die Konfigurationsdatei

● Laden Sie das event.php-Ereignis im Anwendungsverzeichnis

● Registrieren Sie den service.php-Dienst im Anwendungsverzeichnis

● Laden Sie das Sprachpaket

● Hören Sie sich das AppInit-Ereignis an . Sie können dieses Ereignis nutzen, um einige Voranfragen zu erledigen

● Zeitzone festlegen

● Alle Dienste einbinden und den Dienst starten

Dienstregistrierung

Führen Sie während des Initialisierungsprozesses eine Dienstregistrierung durch. Was bewirkt die Dienstregistrierung? Wie nutzt man den Dienst?

public function register($service, bool $force = false)
{
    $registered = $this->getService($service);
    if ($registered && !$force) {
        return $registered;
    }
    if (is_string($service)) {
        $service = new $service($this);
    }
    if (method_exists($service, 'register')) {
        $service->register();
    }
    if (property_exists($service, 'bind')) {
        $this->bind($service->bind);
    }
    $this->services[] = $service;
}

● Ob der Dienst registriert wurde, ob eine erneute Registrierung erzwungen werden muss

● Instanziieren Sie den Dienst

● Wenn der Wenn die Registermethode implementiert ist, muss sie ausgeführt werden. Registermethode

● Wenn das Bindungsattribut festgelegt ist, muss die Dienstinstanz an den Container gebunden werden.

● Schließlich wird sie in das gesamte Dienstarray zusammengeführt , wartet auf den Start

Dienststart

Derzeit gibt es während der Initialisierung nur die folgenden drei Dienste im $this->initializers-Array

foreach ($this->initializers as $initializer) {
        $this->make($initializer)->init($this);
}

Diese drei Dienste sind:

think\initializer\BootService
think\initializer\Error
think\initializer\RegisterService

● Der Fehlerdienst wird zur Behandlung von Framework-Ausnahmen und -Fehlern verwendet.

● RegisterService bedeutet wörtlich „Dienste registrieren“

● BootService soll Dienste aktivieren

Die Fehlerbehandlung wird später besprochen.

Wenn der RegisterService aus dem Container erstellt wird

Es gibt eine versteckte statische Methode make. Jedes Mal, wenn das Instanzobjekt zum ersten Mal aus dem Container erstellt wird, wird die make-Methode ausgeführt. Natürlich muss es zuerst sein Sie implementieren die Methode.

Die Init-Methode wird dann ausgeführt. Wenn Sie RegisterService eingeben, wird diese Methode angezeigt. Der Inhalt der Methode ist wie folgt:

public function init(App $app)
{
    $file = $app->getRootPath() . 'runtime' . DIRECTORY_SEPARATOR . 'services.php';
    $services = $this->services;
    if (is_file($file)) {
        $services = array_merge($services, include $file);
    }
    foreach ($services as $service) {
        if (class_exists($service)) {
            $app->register($service);
        }
    }
}

Diese Methode ist sehr seltsam, ein wenig anders als ich es mir vorgestellt habe. Der Dienst wird direkt aus dem Laufzeitverzeichnis bezogen, nicht aus service.php im Konfigurationsverzeichnis. Warum passiert das? Aufgrund der Entwicklung von Composer kann das TP-Framework auch eine automatische Erkennung von Paketen ermöglichen, was auch beweist, dass das Entwicklungsteam immer näher an die Community heranrückt. Werfen wir einen Blick darauf, wie dies erreicht wird.

Da dies alles auf Composer zurückzuführen ist, schauen Sie sich Composer.json unter rootPath an. Gehen Sie nach unten und Sie finden die folgende Konfiguration:

"scripts": {
    "post-autoload-dump": [
        "@php think service:discover",
        "@php think vendor:publish"
    ]
}

Von Aus Konfigurationssicht stellt das Framework insgesamt zwei Anweisungen bereit: service:discover und Vendor:publish. Ich werde hier nicht auf die spezifische Implementierung eingehen. Sie müssen nur wissen, dass die Paketerkennung von service:discover implementiert wird.

Außerdem werden standardmäßig drei Dienste eingefügt.

PaginatorService::class,
ValidateService::class,
ModelService::class,

Schließlich werfen wir einen Blick auf BootService. Das ist ganz einfach. Aus der Sicht des Namens ist es nicht schwer zu erkennen, dass es sich im Folgenden um den Code zum normalen Starten des Dienstes handelt. Hier muss jedoch erklärt werden, dass die Startmethode in der Dienstklasse implementiert werden muss, bevor sie gestartet werden kann.

public function init(App $app)
{
    $app->boot();
}

Weitere verwandte ThinkPHP-Kenntnisse finden Sie im ThinkPHP-Tutorial!

Das obige ist der detaillierte Inhalt vonThinkPHP6-Anwendungsinitialisierung (Quellcode-Analyse). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:cnblogs.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen