Heim  >  Artikel  >  PHP-Framework  >  Analysieren Sie den ThinkPHP5-Ladevorgang

Analysieren Sie den ThinkPHP5-Ladevorgang

Guanhui
Guanhuinach vorne
2020-06-11 09:34:482753Durchsuche

Analysieren Sie den ThinkPHP5-Ladevorgang

ThinkPHP installieren

Ich werde nicht näher auf die Installation eingehen. Das offizielle Dokument – ​​Installation ThinkPHP erklärt viel Alles in allem können Sie das Zip-Paket über Composer, Git herunterladen oder direkt zur offiziellen Website von ThinkPHP gehen. Die von mir installierte Version ist 5.0.24

Testlauf

Wenn das Projekt-Download-Verzeichnis nach dem Herunterladen und Installieren das Projektstammverzeichnis Ihres lokalen Servers ist, können Sie direkt die Adresse http://localhost/thinkphp5/public/ in den Browser eingeben, um die Standard-Willkommensseite aufzurufen von ThinkPHP5, wie in der Abbildung unten gezeigt, zeigt an, dass ThinkPHP5 erfolgreich installiert wurde

Analysieren Sie den ThinkPHP5-Ladevorgang

Zusätzlich zur oben genannten Methode des Adressvorgangs können wir auch einen virtuellen Host über konfigurieren Apache oder Nginx, um auf das Projekt zuzugreifen. Interessierte können es sich online ansehen. Spezielles Tutorial und dann den virtuellen Host für den Zugriff konfigurieren.

Kommen wir zur Sache, analysieren wir Schritt für Schritt den Ausführungsprozess von ThinkPHP5...

Eintragsdatei (publicindex.php)

Öffnen Sie die Datei publicindex.php. Schließlich können wir sehen, dass der Originalcode der Eintragsdatei wie folgt lautet

// [ 应用入口文件 ]
// 定义应用目录
define('APP_PATH', __DIR__ . '/../application/');
// 加载框架引导文件
require __DIR__ . '/../thinkphp/start.php';

Der Code der Eintragsdatei ist sehr prägnant, nur zwei Codezeilen, und die Funktionen sind entsprechend

define('APP_PATH', __DIR__ . '/../application/');定义应用目录的常量APP_PATH
require __DIR__ . '/../thinkphp/start.php';加载框架引导文件

Zusätzlich zu den beiden oben genannten Funktionen können wir auch unsere eigenen Konstanten in der Eintragsdatei definieren, zum Beispiel eine Codezeile hinzufügen define('PUBLIC_PATH', __DIR__ .'/../public') ; um die Konstanten des öffentlichen Verzeichnisses und einige Vorverarbeitungen usw. zu definieren.

Laden Sie die Framework-Bootdatei (thinkphpstart.php)

Ähnlich nach Eingabe von thinkphpstart. In der PHP-Datei können wir erkennen, dass nicht viel Code vorhanden ist

namespace think;
// ThinkPHP 引导文件
// 1. 加载基础文件
require __DIR__ . '/base.php';
// 2. 执行应用
App::run()->send();

Aus diesem kurzen Code können wir erkennen, dass es zwei Hauptteile links und rechts gibt

require __DIR__ . '/base.php';加载基础文件
App::run()->send();执行应用

Das Folgende Zwei große Punkte werden im Detail vorstellen, was diese beiden linken und rechten Teile bewirken.

Grundlagendatei laden (thinkphpbase.php)

Wir fahren mit dem Öffnen der Datei thinkphpbase.php fort und stelle fest, dass diese Datei nicht mehr wie die ersten beiden Dateien ist, mit nur zwei Codezeilen...

define('THINK_VERSION', '5.0.24');
define('THINK_START_TIME', microtime(true));
define('THINK_START_MEM', memory_get_usage());
define('EXT', '.php');
define('DS', DIRECTORY_SEPARATOR);
defined('THINK_PATH') or define('THINK_PATH', __DIR__ . DS);
define('LIB_PATH', THINK_PATH . 'library' . DS);
define('CORE_PATH', LIB_PATH . 'think' . DS);
define('TRAIT_PATH', LIB_PATH . 'traits' . DS);
defined('APP_PATH') or define('APP_PATH', dirname($_SERVER['SCRIPT_FILENAME']) . DS);
defined('ROOT_PATH') or define('ROOT_PATH', dirname(realpath(APP_PATH)) . DS);
defined('EXTEND_PATH') or define('EXTEND_PATH', ROOT_PATH . 'extend' . DS);
defined('VENDOR_PATH') or define('VENDOR_PATH', ROOT_PATH . 'vendor' . DS);
defined('RUNTIME_PATH') or define('RUNTIME_PATH', ROOT_PATH . 'runtime' . DS);
defined('LOG_PATH') or define('LOG_PATH', RUNTIME_PATH . 'log' . DS);
defined('CACHE_PATH') or define('CACHE_PATH', RUNTIME_PATH . 'cache' . DS);
defined('TEMP_PATH') or define('TEMP_PATH', RUNTIME_PATH . 'temp' . DS);
defined('CONF_PATH') or define('CONF_PATH', APP_PATH); // 配置文件目录
defined('CONF_EXT') or define('CONF_EXT', EXT); // 配置文件后缀
defined('ENV_PREFIX') or define('ENV_PREFIX', 'PHP_'); // 环境变量的配置前缀
// 环境常量
define('IS_CLI', PHP_SAPI == 'cli' ? true : false);
define('IS_WIN', strpos(PHP_OS, 'WIN') !== false);
// 载入Loader类
require CORE_PATH . 'Loader.php';
// 加载环境变量配置文件
if (is_file(ROOT_PATH . '.env')) {
    $env = parse_ini_file(ROOT_PATH . '.env', true);
    foreach ($env as $key => $val) {
        $name = ENV_PREFIX . strtoupper($key);
        if (is_array($val)) {
            foreach ($val as $k => $v) {
                $item = $name . '_' . strtoupper($k);
                putenv("$item=$v");
            }
        } else {
            putenv("$name=$val");
        }
    }
}
// 注册自动加载
\think\Loader::register();
// 注册错误和异常处理机制
\think\Error::register();
// 加载惯例配置文件
\think\Config::set(include THINK_PATH . 'convention' . EXT);

Bei näherer Betrachtung stellte ich fest, dass der Code zwar mehr als 60 Zeilen umfasst, die Funktionen von Der Code ist offensichtlich. Die Hauptfunktionen sind wie folgt:

  1. Verwenden der Funktion define('', '') zum Definieren vieler Systemkonstanten plus zwei. Eine Umgebungskonstante
  2. führt die Loader-Klasse ein (thinkphplibrarythinkloader .php) zur späteren Verwendung
  3. lädt die Umgebungsvariablen-Konfigurationsdatei (die Umgebungsvariablen-Konfigurationsdatei heißt .env. Diese Datei existiert nicht unbedingt. Sie wird bei Bedarf während des eigentlichen Entwicklungsprozesses hinzugefügt)
  4. Aufruf thinkLoader::register()Automatischen Lademechanismus registrieren
    • System für automatisches Laden registrieren
    • ComposerAutomatische Ladeunterstützung
    • Namespace-Definition registrieren
    • Laden Sie die Zuordnungsdatei der Klassenbibliothek, die im runtimeCache-Verzeichnis vorhanden ist und Fehlerbehandlungsmechanismusclassmap.php
    • Laden Sie die Konventionskonfigurationsdatei (thinkphpconvention.php)
    • extend
    Führen Sie die Anwendung aus (thinkphplibrarythinkApp.php) Die Ausführungsmethode
  5. thinkError::register()Der Einfachheit halber, obwohl der Code dieser Ausführungsmethode etwas lang ist, entscheide ich mich dennoch, die gesamte Methode zu posten, bitte nicht umhauen
  6. /**
     * 执行应用程序
     * @access public
     * @param  Request $request 请求对象
     * @return Response
     * @throws Exception
     */
    public static function run(Request $request = null)
    {
        $request = is_null($request) ? Request::instance() : $request;
        try {
            $config = self::initCommon();
            // 模块/控制器绑定
            if (defined('BIND_MODULE')) {
                BIND_MODULE && Route::bind(BIND_MODULE);
            } elseif ($config['auto_bind_module']) {
                // 入口自动绑定
                $name = pathinfo($request->baseFile(), PATHINFO_FILENAME);
                if ($name && 'index' != $name && is_dir(APP_PATH . $name)) {
                    Route::bind($name);
                }
            }
            $request->filter($config['default_filter']);
            // 默认语言
            Lang::range($config['default_lang']);
            // 开启多语言机制 检测当前语言
            $config['lang_switch_on'] && Lang::detect();
            $request->langset(Lang::range());
            // 加载系统语言包
            Lang::load([
                THINK_PATH . 'lang' . DS . $request->langset() . EXT,
                APP_PATH . 'lang' . DS . $request->langset() . EXT,
            ]);
            // 监听 app_dispatch
            Hook::listen('app_dispatch', self::$dispatch);
            // 获取应用调度信息
            $dispatch = self::$dispatch;
            // 未设置调度信息则进行 URL 路由检测
            if (empty($dispatch)) {
                $dispatch = self::routeCheck($request, $config);
            }
            // 记录当前调度信息
            $request->dispatch($dispatch);
            // 记录路由和请求信息
            if (self::$debug) {
                Log::record('[ ROUTE ] ' . var_export($dispatch, true), 'info');
                Log::record('[ HEADER ] ' . var_export($request->header(), true), 'info');
                Log::record('[ PARAM ] ' . var_export($request->param(), true), 'info');
            }
            // 监听 app_begin
            Hook::listen('app_begin', $dispatch);
            // 请求缓存检查
            $request->cache(
                $config['request_cache'],
                $config['request_cache_expire'],
                $config['request_cache_except']
            );
            $data = self::exec($dispatch, $config);
        } catch (HttpResponseException $exception) {
            $data = $exception->getResponse();
        }
        // 清空类的实例化
        Loader::clearInstance();
        // 输出数据到客户端
        if ($data instanceof Response) {
            $response = $data;
        } elseif (!is_null($data)) {
            // 默认自动识别响应输出类型
            $type = $request->isAjax() ?
            Config::get('default_ajax_return') :
            Config::get('default_return_type');
            $response = Response::create($data, $type);
        } else {
            $response = Response::create();
        }
        // 监听 app_end
        Hook::listen('app_end', $response);
        return $response;
    }
  7. Das sind etwa 90 Zeilen. Was genau macht der Code? In Kombination mit der Annotationsanalyse verfügt es hauptsächlich über die folgenden Funktionen
  • Schritt 1: Verarbeiten Sie die Variable $request, um sicherzustellen, dass sie gültig und nicht null ist
  • Schritt 2: self::initCommon()Rufen Sie die initCommon()-Methode im aktuellen Controller auf, der verantwortlich ist zum Initialisieren der Anwendung. Und geben Sie die Konfigurationsinformationen zurück
    • Loader::addNamespace(self::$namespace, APP_PATH);Registrieren Sie den Namespace
    • self::init()Rufen Sie die init()-Methode dieser Klasse auf, um die Anwendung zu initialisieren
      • Laden Sie verschiedene Konfigurationsdateien
      • Verhaltenserweiterungsdateien laden
      • Öffentliche Dateien laden
      • Sprachpakete laden
    • App-Debug-Modus-bezogene Verarbeitung
    • Zusätzliche Dateien laden, verwandte Dateien über den Wert des Konfigurationselements laden extra_file_list
    • date_default_timezone_set($config['default_timezone']);Systemzeitzone festlegen
    • Aufruf Hook::listen('app_init');Das Verhalten der Überwachung des app_init-Tag
  • Schritt 3: Bestimmen Sie, ob das Modul oder der Controller gebunden werden soll
  • Schritt 4: Einstellung und Laden der Systemsprache
  • Schritt 5:self::routeCheck($request, $config)Laden Sie die RouteCheck der aktuellen Controller ()-Methode zur Routing-Erkennung
    • Führen Sie zunächst die Erkennung der Routing-Adresskonfiguration durch, lesen Sie zuerst die zwischengespeicherte Route, falls diese nicht vorhanden ist, und importieren Sie dann die Routing-Dateikonfiguration
    • Analysieren Sie ohne Routing-Konfiguration direkt das Modul/den Controller/die Operation
    • Modulinformationen (Modulname, Controllername und Name der Betriebsmethode) zurückgeben
  • Schritt 6: Drehen im Debug-Modus und zeichnen Sie das Protokoll der Routing- und Anforderungsinformationen auf
  • Schritt 7: self::exec($dispatch, $config)Rufen Sie die exec()-Methode im Controller auf, um die Anrufverteilung durchzuführen
    • Verteilungsverarbeitung gemäß durchführen Benutzeranforderungstyp, hier ist der Modulmodultyp
    • Aufruf self::module()Führen Sie das Modul aus, führen Sie die Modulbereitstellung und -initialisierung durch, rufen Sie den aktuellen Controllernamen und den Operationsnamen ab und legen Sie ihn fest
  • Schritt 8: Löschen Sie die Instanziierung der Klasse und geben Sie die Daten im entsprechenden Format an den Client aus, d. h. die vom Benutzer gesehene Ausgabeschnittstelle

Empfohlene Tutorials: " PHP" "ThinkPHP-Tutorial"

Das obige ist der detaillierte Inhalt vonAnalysieren Sie den ThinkPHP5-Ladevorgang. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

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