Thinkphp 5クラスロードメカニズム

38132 ワード

Thinkphp 5クラスロードメカニズム
PS:Thinkphpフレームワークまたは他のMVCフレームワークを熟知している場合に適用され、ネーミングスペースおよび自動ロードクラスについて、一定の理解を持つプログラム関係者が視聴する(実際には自分に書く>
私はずっとthinkphp 5のロード実行時に何をしましたか.彼はどのように自動的にクラスをロードしましたか.composerと同じですか.実行時にクラスを再ロードできるかどうか、テストをして、ロードプロセス全体を追跡しました.
 
文書単位で説明する:
入口ファイルphp
//       
define('APP_PATH', __DIR__ . '/../application/');
//         
require __DIR__ . '/../thinkphp/start.php';

 
1.APP_が定義されているPATH定数
2.start.をロードphpファイル
 
start.phpファイル

namespace think;

// ThinkPHP     
//       
require __DIR__ . '/base.php';
//     
App::run()->send();

 
1.base.をロードphp
2.Appクラスの静的メソッドrun()を実行し、戻り値send()メソッドを実行する
ここに来て、2つの問題が発生しました.Appクラス..どこからロードされたのでしょうか?見てみろphp
 
base.phpファイル

define('THINK_VERSION', '5.0.3');
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);

 
1.多くの定数が定義されている
2.Loaderクラスの読み込み
3.環境変数プロファイルの有無を確認し、ある場合はロードする
4.Loaderクラスを実行するregister()メソッド
5.Errorクラスを実行するregister()メソッド
 
コンテキストおよび注釈から分かるように,Loaderクラスの静的メソッドregister()メソッドであり,クラスの自動ロードを実現しているはずである.ポイントはそれです.
 
Loaderクラスの静的メソッドregister()メソッド
//         
public static function register($autoload = '')
{
    //         
    spl_autoload_register($autoload ?: 'think\\Loader::autoload', true, true);
    //         
    self::addNamespace([
        'think'    => LIB_PATH . 'think' . DS,
        'behavior' => LIB_PATH . 'behavior' . DS,
        'traits'   => LIB_PATH . 'traits' . DS,
    ]);
    //         
    if (is_file(RUNTIME_PATH . 'classmap' . EXT)) {
        self::addClassMap(__include_file(RUNTIME_PATH . 'classmap' . EXT));
    }

    // Composer      
    if (is_dir(VENDOR_PATH . 'composer')) {
        self::registerComposerLoader();
    }

    //     extend  
    self::$fallbackDirsPsr4[] = rtrim(EXTEND_PATH, DS);
}

 
1.デフォルト$autoloadは空で、PHP内蔵関数spl_を使用autoload_register登録Loaderクラスの静的メソッドautoload()メソッドは自動ロードメカニズムです.
クラスを使用すると、クラスが見つからないか含まれていない場合、クラス名をautoload()メソッドに渡して処理させるという意味です.
2.ネーミングスペース定義を登録し、ネーミングスペースを実際のファイルパスに対応させ、クラス静的変数配列に格納します.
その役割はautoload()メソッドでクラスの名前を受信した場合,クラスが属するネーミングスペースを介してクラスファイルの真のパスを見つけ,さらにクラスファイルにincludeを含めることである.
3.以下の基本は同じロードですが、フレームワーク自体のクラスファイルをロードするのではなく、composerライブラリや自分で書いたクラスをロードします.
 
Autoload()メソッド
//     
public static function autoload($class)
{
    //         
    if (!empty(self::$namespaceAlias)) {
        $namespace = dirname($class);
        if (isset(self::$namespaceAlias[$namespace])) {
            $original = self::$namespaceAlias[$namespace] . '\\' . basename($class);
            if (class_exists($original)) {
                return class_alias($original, $class, false);
            }
        }
    }

    if ($file = self::findFile($class)) {

        // Win         
        if (IS_WIN && pathinfo($file, PATHINFO_FILENAME) != pathinfo(realpath($file), PATHINFO_FILENAME)) {
            return false;
        }

        __include_file($file);
        return true;
    }
}

 
ご覧のようにautoloadメソッドは、クラス名を受信し、クラスファイルを検索し、クラスファイルを含む方法です.
 
はい、これでThinkphp 5の実行時にクラスをロードする流れが明らかになりました.
まとめてphpロードstart.php、start.phpにbaseをロードする.php(クラス自動ロードメカニズムはここにあります)、次にAppの静的メソッドrunメソッドを呼び出して「モジュール/コントローラ/操作」を実行し、Resposeクラスのインスタンスに戻ってsendメソッドを実行し、応答データをクライアントに送信すると、完全な要求が完了します. 
付録:
各ファイルのパス:
index.php
\think5\public
 
start.php
\think5\thinkphp
 
base.php
\think5\thinkphp
 
Loader.php
\think5\thinkphp\library\think
 
spl_の場合autoload_registerと自動ロードに疑問があるか分からないのは私の別のブログを見てもいいです.
__autoload,spl_autoload_registerと自動ロード