Maison >cadre php >PensezPHP >Analyser le processus de chargement de ThinkPHP5

Analyser le processus de chargement de ThinkPHP5

Guanhui
Guanhuiavant
2020-06-11 09:34:482881parcourir

Analyser le processus de chargement de ThinkPHP5

Installation de ThinkPHP

Je n'entrerai pas dans les détails sur la façon de l'installer. Le document officiel - Installation. ThinkPHP explique beaucoup de choses. Dans l'ensemble, vous pouvez télécharger le package zip via Composer, Git ou accéder directement au site officiel de ThinkPHP. La version que j'ai installée est la 5.0.24

Test<.>

Après le téléchargement et l'installation, si le répertoire de téléchargement du projet est le répertoire racine du projet de votre serveur local, vous pouvez directement saisir l'adresse http://localhost/thinkphp5/public/ dans le navigateur pour accéder à la page d'accueil par défaut de ThinkPHP5, comme le montre la figure ci-dessous. Indique que ThinkPHP5 a été installé avec succès

Analyser le processus de chargement de ThinkPHP5

En plus de la méthode d'opération d'adresse ci-dessus, nous pouvons également configurer un hôte virtuel via Apache ou Nginx pour accéder au projet. Ceux qui sont intéressés peuvent le consulter en ligne Tutoriel spécifique, puis configurer l'hôte virtuel pour y accéder.

Entrons dans le vif du sujet, analysons le processus d'exécution de ThinkPHP5 étape par étape...

Fichier d'entrée (publicindex.php)

Ouvrez le fichier publicindex.php Enfin, nous pouvons voir que le code original du fichier d'entrée est le suivant

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

Le code du fichier d'entrée est très concis, juste deux lignes de code, et les fonctions sont respectivement

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

En plus des deux fonctions ci-dessus, nous pouvons également définir nos propres constantes dans le fichier d'entrée, comme l'ajout d'une ligne de code finish('PUBLIC_PATH', __DIR__ .'/../public'); pour définir les constantes du répertoire public et quelques prétraitements, etc.

Chargez le fichier de démarrage du framework (thinkphpstart.php)

De même, après avoir entré le thinkphpstart.php fichier, on peut savoir qu'il n'y a pas beaucoup de code

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

De ce court Dans les deux lignes de code, on peut voir qu'il y a deux parties principales gauche et droite

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

Les deux suivantes les grands points présenteront en détail ce que font ces deux parties gauche et droite

Chargement du fichier de base (thinkphpbase.php)

Nous continuons à ouvrir le fichier thinkphpbase.php et constate que ce fichier n'est plus comme les deux premiers fichiers, avec seulement deux lignes de code...

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

Après y avoir regardé de plus près, j'ai constaté que bien que le code comporte plus de 60 lignes, les fonctions du le code sont évidents. Les fonctions principales sont les suivantes :

    Utiliser la fonction
  1. pour définir de nombreuses constantes système, plus deux Une constante d'environnement define('', '')
  2. introduit la classe de chargement (thinkphplibrarythinkloader. php) pour une utilisation ultérieure
  3. charge le fichier de configuration des variables d'environnement (le fichier de configuration des variables d'environnement est nommé
  4. . Ce fichier n'existe pas nécessairement. Il est ajouté selon les besoins lors du processus de développement proprement dit) .env
  5. Appel
  6. Enregistrer le mécanisme de chargement automatiquethinkLoader::register()
      Enregistrer le système pour le chargement automatique
    • Prise en charge du chargement automatiqueComposer
    • Enregistrer la définition de l'espace de noms
    • Charger le fichier de mappage de la bibliothèque de classes, qui existe dans le
    • répertoire de cacheruntimeclassmap.php
    • Charger automatiquement le
    • répertoireextend
  7. Appeler
  8. Enregistrer l'exception et mécanisme de gestion des erreursthinkError::register()
  9. Charger le fichier de configuration de la convention (thinkphpconvention.php)

Exécuter l'application (thinkphplibrarythinkApp.php) La méthode run

Pour plus de commodité, bien que le code de cette méthode d'exécution soit un peu long, je choisis quand même de publier l'intégralité de la méthode, ne me frappez pas

/**
 * 执行应用程序
 * @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(&#39;BIND_MODULE&#39;)) {
            BIND_MODULE && Route::bind(BIND_MODULE);
        } elseif ($config[&#39;auto_bind_module&#39;]) {
            // 入口自动绑定
            $name = pathinfo($request->baseFile(), PATHINFO_FILENAME);
            if ($name && &#39;index&#39; != $name && is_dir(APP_PATH . $name)) {
                Route::bind($name);
            }
        }
        $request->filter($config[&#39;default_filter&#39;]);
        // 默认语言
        Lang::range($config[&#39;default_lang&#39;]);
        // 开启多语言机制 检测当前语言
        $config[&#39;lang_switch_on&#39;] && Lang::detect();
        $request->langset(Lang::range());
        // 加载系统语言包
        Lang::load([
            THINK_PATH . &#39;lang&#39; . DS . $request->langset() . EXT,
            APP_PATH . &#39;lang&#39; . DS . $request->langset() . EXT,
        ]);
        // 监听 app_dispatch
        Hook::listen(&#39;app_dispatch&#39;, self::$dispatch);
        // 获取应用调度信息
        $dispatch = self::$dispatch;
        // 未设置调度信息则进行 URL 路由检测
        if (empty($dispatch)) {
            $dispatch = self::routeCheck($request, $config);
        }
        // 记录当前调度信息
        $request->dispatch($dispatch);
        // 记录路由和请求信息
        if (self::$debug) {
            Log::record(&#39;[ ROUTE ] &#39; . var_export($dispatch, true), &#39;info&#39;);
            Log::record(&#39;[ HEADER ] &#39; . var_export($request->header(), true), &#39;info&#39;);
            Log::record(&#39;[ PARAM ] &#39; . var_export($request->param(), true), &#39;info&#39;);
        }
        // 监听 app_begin
        Hook::listen(&#39;app_begin&#39;, $dispatch);
        // 请求缓存检查
        $request->cache(
            $config[&#39;request_cache&#39;],
            $config[&#39;request_cache_expire&#39;],
            $config[&#39;request_cache_except&#39;]
        );
        $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(&#39;default_ajax_return&#39;) :
        Config::get(&#39;default_return_type&#39;);
        $response = Response::create($data, $type);
    } else {
        $response = Response::create();
    }
    // 监听 app_end
    Hook::listen(&#39;app_end&#39;, $response);
    return $response;
}

Cela fait environ 90 lignes. Que fait exactement le code Combiné ? avec l'analyse des annotations, il a principalement les fonctions suivantes

  • Étape 1 : Traitez la variable $request pour vous assurer qu'elle est valide et non nulle
  • Étape 2 : self::initCommon()Appelez la méthode initCommon() dans le contrôleur actuel, qui est responsable pour initialiser l'application. Et renvoyer les informations de configuration
    • Loader::addNamespace(self::$namespace, APP_PATH);Enregistrer l'espace de noms
    • self::init()Appelez la méthode init() de cette classe pour initialiser l'application
      • Charger divers fichiers de configuration
      • Charger les fichiers d'extension de comportement
      • Charger les fichiers publics
      • Charger les modules linguistiques
    • Traitement lié au mode de débogage de l'application
    • Charger des fichiers supplémentaires, charger les fichiers associés via la valeur de l'élément de configuration extra_file_list
    • date_default_timezone_set($config['default_timezone']);Définir le fuseau horaire du système
    • Appeler Hook::listen('app_init');Le comportement de surveillance du balise app_init
  • Étape 3 : Déterminer s'il faut lier le module ou le contrôleur
  • Étape 4 : Paramétrage et chargement de la langue du système
  • Étape 5 :self::routeCheck($request, $config)Charger la méthode routeCheck du contrôleur actuel () pour la détection de routage
    • Effectuez d'abord la détection de la configuration de l'adresse de routage, lisez d'abord la route mise en cache, si elle n'existe pas, puis importez la configuration du fichier de routage
    • Sans configuration de routage, analysez directement le module/contrôleur/opération
    • Renvoyer les informations du module du module (nom du module, nom du contrôleur et nom de la méthode de fonctionnement)
  • Étape 6 : Tourner en mode débogage et enregistrez le journal des informations de routage et de demande
  • Étape 7 : self::exec($dispatch, $config)Appelez la méthode exec() dans le contrôleur pour effectuer la distribution des appels
    • Effectuez le traitement de distribution selon le type de demande utilisateur, voici le type de module du module
    • appeler self::module()Exécuter le module, effectuer le déploiement et l'initialisation du module, obtenir et définir le nom actuel du contrôleur et le nom de l'opération
  • Étape 8 : Effacer l'instanciation de la classe et afficher les données dans le format correspondant vers le client, c'est-à-dire l'interface de sortie vue par l'utilisateur

Tutoriels recommandés : " PHP" "Tutoriel ThinkPHP"

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer