天天看点

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

支持或许会对你有些许帮助。