<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                > ### ThinkPHP實現類的加載核心函數 **spl_autoload_register()** 首先我們來看看魔術方法\_\_autoload(),這是一個自動加載函數,在PHP5中,當我們實例化一個未定義的類時,就會觸發此函數。 Goods類 ``` class Goods { public function order() { return 'phone'.PHP_EOL; } } ``` test_autoload.php 文件 ``` function __autoload($class_name = "") { echo 'class:' . $class_name . PHP_EOL; include "./{$class_name}.php"; } $goods = new Goods(); echo $goods->order(); ``` 執行結果 ``` bash-5.0# php test_autoload.php class:Goods phone ``` cli 模式運行 `test_autoload.php` 后正常打印 phone。在` test_autoload.php` 中,由于沒有包含Goods.php,在實例化Goods類時,自動調用`_autoload`函數,參數`$class_name`的值即為類名`Goods`,此時`Goods`就被引進來了。在面向對象中這種方法經常使用,可以避免書寫過多的引用文件。 >[danger] 注意:`__autoload` 自PHP 7.2.0起已棄用此功能 ,[更多了解/function.autoload.php](https://www.php.net/manual/zh/function.autoload.php) test_autoload_register.php 文件 ``` spl_autoload_register('autoload', true, true); function autoload($class_name = '') { echo 'class:' . $class_name . PHP_EOL; include "./{$class_name}.php"; } $goods = new Goods(); echo $goods->order(); ``` 執行結果 ``` bash-5.0# php test_autoload_register.php class:Goods phone ``` 分析: 將魔術方法`__autoload`換成`autoload`函數。`autoload()`只是一個普通的函數,不會像`__autoload`自動觸發,這時`spl_autoload_register()`就起作用了,它告訴PHP碰到沒有定義的類就執行`autoload()`函數。 >[warning] `spl_autoload_register` — 注冊給定的函數作為 __autoload 的實現,[更多]([https://www.php.net/manual/zh/function.spl-autoload-register.php](https://www.php.net/manual/zh/function.spl-autoload-register.php)) > ### 入口文件 在入口文件中引入了 base.php ``` namespace think; // 載入Loader類 require __DIR__ . '/library/think/Loader.php'; // 注冊自動加載 Loader::register(); ... ``` Loader::register() 方法 ``` // 注冊自動加載機制 public static function register($autoload = '') { // 注冊系統自動加載 spl_autoload_register($autoload ?: 'think\\Loader::autoload', true, true); // 變量值:/var/www/wiot.tinywan.com/ $rootPath = self::getRootPath(); self::$composerPath = $rootPath . 'vendor' . DIRECTORY_SEPARATOR . 'composer' . DIRECTORY_SEPARATOR; // Composer自動加載支持 if (is_dir(self::$composerPath)) { if (is_file(self::$composerPath . 'autoload_static.php')) { require self::$composerPath . 'autoload_static.php'; //require $rootPath . 'wiot.tinywan.com/class_autoload/Goods.php'; // 引入自定義類 $declaredClass = get_declared_classes(); // 返回由當前文件中已引入類的名字組成的數組 // $declaredClass數組中的最后一個Composer\Autoload\ComposerStaticInitafad3d1f17f029da67a39c37bf199ba7 $composerClass = array_pop($declaredClass); foreach (['prefixLengthsPsr4', 'prefixDirsPsr4', 'fallbackDirsPsr4', 'prefixesPsr0', 'fallbackDirsPsr0', 'classMap', 'files'] as $attr) { if (property_exists($composerClass, $attr)) { // 該方法用于檢測類是否存在指定的屬性 self::${$attr} = $composerClass::${$attr}; // 存在則將composer安裝的類的私有屬性,賦值給本類對應的私有屬性 } } } else { self::registerComposerLoader(self::$composerPath); } } // 注冊命名空間定義 將think和traits放到 prefixLengthsPsr4 和 prefixDirsPsr4屬性中 self::addNamespace([ 'think' => __DIR__, 'traits' => dirname(__DIR__) . DIRECTORY_SEPARATOR . 'traits', // 使用dirname()方法返回路徑的目錄部分 'scource' => dirname(__DIR__) . DIRECTORY_SEPARATOR . 'scource', // 實現自定義目錄下面的類自動加載 ]); // 加載類庫映射文件 // 1、默認情況下在runtime目錄下是沒有classmap.php的 // 2、可通過命令 php think optimize:autoload 生成 可以提升性能 if (is_file($rootPath . 'runtime' . DIRECTORY_SEPARATOR . 'classmap.php')) { self::addClassMap(__include_file($rootPath . 'runtime' . DIRECTORY_SEPARATOR . 'classmap.php')); } // 自動加載extend目錄 self::addAutoLoadDir($rootPath . 'extend'); // 實現自定義目錄下面的類自動加載 self::addAutoLoadDir($rootPath . 'scource'); } ``` 分析: 1、base.php 中調用`register`方法時傳參為空,所以`$autoload = ''`,所以Loader類會調用本類的`autoload()`方法,這里跟上面將的原理是一樣的,`autoload()`方法我們后面分析。 ``` // 自動加載 public static function autoload($class) { if (isset(self::$classAlias[$class])) { return class_alias(self::$classAlias[$class], $class); } if ($file = self::findFile($class)) { // Win環境嚴格區分大小寫 if (strpos(PHP_OS, 'WIN') !== false && pathinfo($file, PATHINFO_FILENAME) != pathinfo(realpath($file), PATHINFO_FILENAME)) { return false; } __include_file($file); return true; } } ``` 2、composer安裝的擴展類庫加載,會找到`composer/autoload_static.php`,這里可以引入我們想要自動加載的類,例如代碼中引入了我們剛剛自定義的`Good`類,這是引入自定義類的一種方法,后面我們還會介紹其他方法。 3、`$declaredClass = get_declared_classes()` 返回一個數組,數組是當前文件中已引入類的名字,可以自行斷點調試,這里我貼上部分結果 ``` Array ( [0] => stdClass [1] => Exception [2] => ErrorException [3] => Error [74] => ParentIterator [91] => RecursiveDirectoryIterator [105] => PDOException [106] => PDO [107] => PDOStatement [133] => Redis [134] => RedisArray [135] => RedisCluster [136] => RedisException [137] => RedisClusterException [138] => AMQPConnection [139] => AMQPChannel [140] => AMQPQueue [141] => AMQPExchange [153] => PharException [158] => mysqli_driver [159] => mysqli [166] => Swoole\Error [192] => Swoole\Coroutine\Iterator [248] => Swoole\Redis\Server [250] => Yaconf [251] => think\Loader [252] => Composer\Autoload\ComposerStaticInit0ec10a4d3a3df1a88bd61e927cf732f4 ) ``` 4、`$composerClass = array_pop($declaredClass); `獲取到`$declaredClass`數組的最后一個,然后進行一個循環,循環體中檢查`autoload_static.php`類中是否存在指定的屬性,存在則`composer`安裝的類的私有屬性賦值給本類對應的私有屬性,這樣Loader類的成員變`$prefixLengthsPsr4`和`$prefixDirsPsr4`都有了`autoload_static.php`中對應的值了 autoload_static.php ``` class ComposerStaticInitafad3d1f17f029da67a39c37bf199ba7 { public static $files = array ( '9b552a3cc426e3287cc811caefa3cf53' => __DIR__ . '/..' . '/topthink/think-helper/src/helper.php', ); /** * @var array * 說明: 1.數組的鍵是值的首字母 例如 't' 是 'think\\composer\\'和 'think\\'的首字母 * 2.對應的數字表示 'think\\composer\\'和 'think\\'的長度,注意兩個\\中有一個是轉義字符 不會被計算到長度中 */ public static $prefixLengthsPsr4 = array ( 't' => array ( 'think\\composer\\' => 15, 'think\\' => 6, ), 'a' => array ( 'app\\' => 4, ), ); /** * @var array * 說明:定義$prefixLengthsPsr4中定義的類的目錄地址 */ public static $prefixDirsPsr4 = array ( 'think\\composer\\' => array ( 0 => __DIR__ . '/..' . '/topthink/think-installer/src', ), 'think\\' => array ( 0 => __DIR__ . '/..' . '/topthink/think-helper/src', ), 'app\\' => array ( 0 => __DIR__ . '/../..' . '/application', ), ); public static function getInitializer(ClassLoader $loader) { return \Closure::bind(function () use ($loader) { $loader->prefixLengthsPsr4 = ComposerStaticInitafad3d1f17f029da67a39c37bf199ba7::$prefixLengthsPsr4; $loader->prefixDirsPsr4 = ComposerStaticInitafad3d1f17f029da67a39c37bf199ba7::$prefixDirsPsr4; }, null, ClassLoader::class); } } ``` 4、注冊命名空間定義,此時$namespace的值為 ``` Array ( [think] => /var/www/wiot.tinywan.com/thinkphp/library/think [traits] => /var/www/wiot.tinywan.com/thinkphp/library/traits [scource] => /var/www/wiot.tinywan.com/thinkphp/library/scource ) ``` 說明一下,這里的scource又是一種我們加入自定義類的方法 ``` // 注冊命名空間 public static function addNamespace($namespace, $path = '') { print_r($namespace);die; if (is_array($namespace)) { foreach ($namespace as $prefix => $paths) { self::addPsr4($prefix . '\\', rtrim($paths, DIRECTORY_SEPARATOR), true); } } else { self::addPsr4($namespace . '\\', rtrim($path, DIRECTORY_SEPARATOR), true); } } ``` 循環`$namespace`調用`addPsr4`方法將`think`和`traits`放到 `prefixLengthsPsr4 `和 `prefixDirsPsr4`屬性中 5、加載類庫映射文件,默認情況下在`runtime`目錄下是沒有`classmap.php`的,可通過命令 `php think optimize:autoload `生成, 可以提升性能,當Loader類調用`findFile()`方法時,如果生成了`classmap.php`文件就直接return了,不然就要一次執行`findFile()`方法下面的查看文件的方法。 6、自動加載`extend`目錄, 會將擴展目錄`extend`目錄地址存放在Loader類的$fallbackDirsPsr4 成員屬性中,這里就衍生出我們的第三種自定義類實現自動加載的方法,我們在項目根目錄中定義`scource`目錄,在其中定義我們的自定義類,在定義的時候要注意命名空間。 (1)自定義目錄下面的類自動加載(二級) ``` // source/tinywan/Email.php namespace tinywan; class Email { public static function send() { echo 'scource-tinywan-Email-send ' . PHP_EOL; } } ``` (2)自定義目錄下面的類自動加載(一級) ``` // source/Sms.php class Sms { public static function send() { echo 'scource-SMS-send' . PHP_EOL; } } ``` (3)自定義目錄下面的類自動加載(一級) ``` //thinkphp/library/source/EmailSend.php namespace source; class EmailSend { public static function send() { echo 'nikki-push' . PHP_EOL; } } ``` 測試類 ``` class Test extends Controller { /** * @desc: 類的自動加載測試用例 * 1、Email::send() 和 Sms::send() 是通過 $fallbackDirsPsr4 實現 * 2、EmailSend::send() 是通過 $prefixLengthsPsr4 $prefixDirsPsr4 實現 */ public function autoLoad() { Email::send(); \Sms::send(); EmailSend::send(); } } ```
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看