composer自動載入執行個體分析

來源:互聯網
上載者:User

通過在composer.json檔案中配置需要載入的類、命名空間,通過執行composer install 命令自動產生類名和對應的類檔案的映射,而後通過註冊loadClass方法,實現對composer管理的諸多類的自動載入;

如何在composer.json檔案中配置類和命名空間 ?

共有四種方式:
PSR-0(網上查到的例子和PSR-4沒有看出太大區別,且已不推薦使用);
PSR-4;
Class-map;
Files;
在composer.json檔案中添加以下代碼塊:

"autoload": {    "psr-4": {        "src\\darren\\": "src/",        "project\\darren\\": "project"        },    "files": ["common/Darren.php", "common/Since.php"],    "classmamp": [lib]}

測試代碼目錄結構如下:

common    Darren.php    Since.phplib    Darren.php    Since.phpproject    Darren.phpsrc    Darren.phpvendorcomposer.jsonindex.php

代碼中的命名空間習慣為:目錄名/Darren
當我們配置好composer.json檔案,並執行compoer install命令後,在vendor/composer目錄下會自動產生一些php檔案,這些檔案實際上記錄了類、命名空間和對應的類檔案的映射,下面一一舉例說明;

PSR-4

如上所述,通過psr-4方式配置了兩個命名空間的自動載入,分別是src\daren和projecr\darren;vendor/composer目錄下自動產生了autoload_psr4.php檔案,具體代碼如下所示:

<?php// autoload_psr4.php @generated by Composer$vendorDir = dirname(dirname(__FILE__));$baseDir = dirname($vendorDir);return array('src\\darren\\' => array($baseDir . '/src'),'project\\darren\\' => array($baseDir . '/project'),);
Classmap方式

classmap方式只需要我們配置需要自動載入的目錄,compoer會自動掃描目錄下的的.php檔案或.inc檔案中的class,並自動產生這些類和其對應的類檔案的映射關係,儲存在vendor/composer目錄下的autoload_classmap.php檔案中,具體代碼如下:

<?php// autoload_classmap.php @generated by Composer$vendorDir = dirname(dirname(__FILE__));$baseDir = dirname($vendorDir);return array('lib\\darren\\Darren' => $baseDir . '/lib/Darren.php','lib\\since\\Since' => $baseDir . '/lib/Since.php',);

其中lib\darren為命名空間,Darren為類名;

Files

files方式其實就是手動指定要載入的檔案,這通常適用於一些全域的functions,可以將這些functions統一放在一個檔案裡,然後直接進行載入;
上述的設定檔通過files方式載入了兩個檔案common/Darren.php和common/Since.php,vendor/composer目錄下自動產生了autoload_files.php檔案,具體代碼如下所示:

<?php// autoload_files.php @generated by Composer$vendorDir = dirname(dirname(__FILE__));$baseDir = dirname($vendorDir);return array('b704865b506bf33e8097e6f62604fc7f' => $baseDir . '/common/Darren.php','603921ee67f9053beb44a88f05b115d2' => $baseDir . '/common/Since.php',);
composer是如何?自動載入的 ?

配置完compoer.json檔案,跑完了composer install命令,在檔案的開始引用vendor/autolaod.php即可實作類別的自動載入,那麼composer是如何?自動載入的呢?

這裡先插敘一點php的特性:當調用不存在的類時,系統會自動調用__autoload( )方法來載入相應的類;

舉例子說明如下:
我們在index.php檔案中調用Darren類中的testAutoload( )方法【Darren類與index.php檔案在同級目錄】,這裡我們沒有在index.php檔案中引入Darren類,那麼肯定是會報錯的;但是我們可以重寫__autoload( )方法實現Darren類的載入,具體代碼如下:

//當調用不存在的類時,系統自動調用__autolaod()尋找function __autolaod($class){    $file = $class . '.php';    if (is_file($file)) {        require_once($file);    }}Darren::testAutoload();

我們也可以通過spl_autoload_register( )方法來註冊一個其它方法來替代__autoload( );

舉例如下:

function loader($class){    $file = $class . '.php';    if (is_file($file)) {        require_once($file);    }}spl_autoload_register('loader');Darren::testAutoload();

這樣,loader方法就取代了__autoload;

接下來我們繼續研究composer背後的載入機制,autoload.php中引入了autoload_real.php然後調用了getLoader( )方法,getLoader( )方法具體代碼如下:

public static function getLoader(){    if (null !== self::$loader) {        return self::$loader;    }    spl_autoload_register(array('ComposerAutoloaderInit0a8197b9e4da93df051721eff8ed7b28', 'loadClassLoader'), true, true);    self::$loader = $loader = new \Composer\Autoload\ClassLoader();    spl_autoload_unregister(array('ComposerAutoloaderInit0a8197b9e4da93df051721eff8ed7b28', 'loadClassLoader'));    $map = require __DIR__ . '/autoload_namespaces.php';    foreach ($map as $namespace => $path) {        $loader->set($namespace, $path);    }    //整理通過psr-4方式配置的類    $map = require __DIR__ . '/autoload_psr4.php';    foreach ($map as $namespace => $path) {        $loader->setPsr4($namespace, $path);    }    //整理通過classmap方式配置的類    $classMap = require __DIR__ . '/autoload_classmap.php';    if ($classMap) {        $loader->addClassMap($classMap);    }    //註冊實現自動載入的方法    $loader->register(true);    //直接引入通過files配置的類    $includeFiles = require __DIR__ . '/autoload_files.php';    foreach ($includeFiles as $fileIdentifier => $file) {        composerRequire0a8197b9e4da93df051721eff8ed7b28($fileIdentifier, $file);    }    return $loader;}

該方法先是建立了一個ClassLoader類的對象,然後載入composer自動產生的那些記錄類、命名空間與檔案對應關係的檔案,調用ClassLoader中的方法對這些檔案整理,並將映射關係通過數組儲存,數組的鍵為類名或者命名空間加類名,數組的值為類對應的類檔案地址;這裡值得注意的一點是,我們通過files配置的那些需要自動載入的類,是直接將類檔案引入進來,並不是在調用時才去載入,代碼如下:

function composerRequire0a8197b9e4da93df051721eff8ed7b28($fileIdentifier, $file){    if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {        require $file;//直接引入類檔案        $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;     }}
ClassLoader類中值得注意的方法:

通過register方法註冊loadClass方法,取代__autoload( )方法,實作類別的載入

public function register($prepend = false){    spl_autoload_register(array($this, 'loadClass'), true, $prepend);}

loadClass方法尋找類對應的檔案,並引入:

public function loadClass($class){    if ($file = $this->findFile($class)) {        includeFile($file);        return true;    }}

具體如何尋找數組從而得到該類對應的類檔案,可以通過xdebug跟一遍代碼,並不難理解;

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.