天天看點

Laravel源碼分析---composer檔案加載

    最近在使用

Laravel

架構,是以分析一下源碼是如何設計的。

首先我們可以在

Laravel

項目的入口檔案看見這些代碼。

<?php

/**
 * Laravel - A PHP Framework For Web Artisans
 *
 * @package  Laravel
 * @author   Taylor Otwell <[email protected]>
 */

define('LARAVEL_START', microtime(true));

/*
|--------------------------------------------------------------------------
| Register The Auto Loader
|--------------------------------------------------------------------------
|
| Composer provides a convenient, automatically generated class loader for
| our application. We just need to utilize it! We'll simply require it
| into the script here so that we don't have to worry about manual
| loading any of our classes later on. It feels great to relax.
|
*/

require __DIR__.'/../vendor/autoload.php'; // (1)

/*
|--------------------------------------------------------------------------
| Turn On The Lights
|--------------------------------------------------------------------------
|
| We need to illuminate PHP development, so let us turn on the lights.
| This bootstraps the framework and gets it ready for use, then it
| will load up this application so that we can run it and send
| the responses back to the browser and delight our users.
|
*/

$app = require_once __DIR__.'/../bootstrap/app.php';  // (2)

/*
|--------------------------------------------------------------------------
| Run The Application
|--------------------------------------------------------------------------
|
| Once we have the application, we can handle the incoming request
| through the kernel, and send the associated response back to
| the client's browser allowing them to enjoy the creative
| and wonderful application we have prepared for them.
|
*/

$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class); // (3)

$response = $kernel->handle(  // (4)
    $request = Illuminate\Http\Request::capture()
);

$response->send();  //(5)

$kernel->terminate($request, $response);  // (6)

           

這裡面我劃分了

6

個點,分别是:

(1)類加載

(2)應用實體類初始化

(3)綁定

http

或者

console

核心

(4)請求處理

(5)結果傳回用戶端

(6)結束請求後的處理操作

這次分析的是類加載。

程式第一次請求,我們會進入

autoload.php

檔案

require_once __DIR__ . '/composer/autoload_real.php';

return ComposerAutoloaderInit859fdbc36eb6d63b36031b6c1db7e16b::getLoader();
           

這裡面

autoload_real.php

是重點,這個類基本上在

composer

中起了入口檔案的功能。它将所有的功能都彙總在一起。

ComposerAutoloaderInit859fdbc36eb6d63b36031b6c1db7e16b::getLoader()

這個就是

autooad_real.php

的類,這裡為什麼會用這麼奇怪的名字?因為這是一個全局的類,為了不讓其他程式員寫出相同的名字,是以添加上一串哈希值。然後我們看看

getLoader

到底是在幹什麼的?

public static function getLoader()
    {
    	//單例,防止多次初始化
        if (null !== self::$loader) {
            return self::$loader;
        }
		//注冊自動加載函數
        spl_autoload_register(array('ComposerAutoloaderInit859fdbc36eb6d63b36031b6c1db7e16b', 'loadClassLoader'), true, true);
        self::$loader = $loader = new \Composer\Autoload\ClassLoader();
        //删除自動加載函數
        spl_autoload_unregister(array('ComposerAutoloaderInit859fdbc36eb6d63b36031b6c1db7e16b', 'loadClassLoader'));
		//檢查PHP版本是否大于等于5.6,是就使用靜态方法調用
        $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
        if ($useStaticLoader) {
            require_once __DIR__ . '/autoload_static.php';
			//調用閉包函數,類預設引用傳遞
            call_user_func(\Composer\Autoload\ComposerStaticInit859fdbc36eb6d63b36031b6c1db7e16b::getInitializer($loader));
        } else {
        	//設定變量映射
            $map = require __DIR__ . '/autoload_namespaces.php';
            foreach ($map as $namespace => $path) {
                $loader->set($namespace, $path);
            }

            $map = require __DIR__ . '/autoload_psr4.php';
            foreach ($map as $namespace => $path) {
                $loader->setPsr4($namespace, $path);
            }

            $classMap = require __DIR__ . '/autoload_classmap.php';
            if ($classMap) {
                $loader->addClassMap($classMap);
            }
        }
		//注冊命名空間加載函數
        $loader->register(true);
		//這也是PHP=5.6就直接調用靜态變量
        if ($useStaticLoader) {
            $includeFiles = Composer\Autoload\ComposerStaticInit859fdbc36eb6d63b36031b6c1db7e16b::$files;
        } else {
            $includeFiles = require __DIR__ . '/autoload_files.php';
        }
        //file檔案加載進來
        foreach ($includeFiles as $fileIdentifier => $file) {
            composerRequire859fdbc36eb6d63b36031b6c1db7e16b($fileIdentifier, $file);
        }

        return $loader;
    }
	
	//加載ClassLoader類
    public static function loadClassLoader($class)
    {
        if ('Composer\Autoload\ClassLoader' === $class) {
            require __DIR__ . '/ClassLoader.php';
        }
    }
           

上面的

composer

加載重點其實在

$loader->register(true);

這個語句就是檔案根據命名空間找到檔案的功能。

/**
     * Registers this instance as an autoloader.
     *
     * @param bool $prepend Whether to prepend the autoloader or not
     */
    public function register($prepend = false)
    {
    	//注冊根據命名空間自動加載類檔案函數
        spl_autoload_register(array($this, 'loadClass'), true, $prepend);
    }

           

根據上面的注釋,很清晰的知道了

composer

究竟在幹了什麼了。然而你或許會疑問那些檔案究竟是怎麼來的,這裡我可以告訴你是在使用

composer install

的時候就已經生成好的了。就這樣子

Laravel

的檔案加載就完成了。

如果你還是不懂,那可能就是

PHP

基礎問題了。可以看看我的

PHP

架構開發教程。隻要跟着架構自己寫一遍之後,你就會發現,其實這裡面沒什麼難以了解的。最主要的還是如何定義命名空間擷取目錄中的檔案問題。而且我的架構開發中的

composer

支援或許會對你有些許幫助。