Samtoto / laravel-review

0 stars 0 forks source link

Day 1 #3

Open Samtoto opened 4 years ago

Samtoto commented 4 years ago

/public/index.php 入口

// file:/public/index.php
require __DIR__.'/../vendor/autoload.php';

引入了 autoload.php

进入 /vendor/autoload.php

<?php
// file:/local/vendor/autoload.php
// autoload.php @generated by Composer

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

return ComposerAutoloaderInit53e7e9fbc7f3b93c224f3bd5f4f6ec3e::getLoader();

引入了 /vendor/composer/autoload_real.php 并调用了 getLoader 方法

进入 /vendor/composer/autoload_real.php

<?php

// autoload_real.php @generated by Composer

class ComposerAutoloaderInit53e7e9fbc7f3b93c224f3bd5f4f6ec3e
{
    private static $loader;

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

    /**
     * @return \Composer\Autoload\ClassLoader
     */
    public static function getLoader()
    {
        if (null !== self::$loader) {
            return self::$loader;
        }
        // 此时上面的if不会执行,因为 self::$loader 是空

        // 注册该 class 和 上面的 loadClassLoader
        spl_autoload_register(array('ComposerAutoloaderInit53e7e9fbc7f3b93c224f3bd5f4f6ec3e', 'loadClassLoader'), true, true);
        // 赋值 由于 ClassLoader 并没有 __construct() 所以继续执行
        // 此时 $loader 为 ClassLoad 类
        self::$loader = $loader = new \Composer\Autoload\ClassLoader();
        // 解除注册
        spl_autoload_unregister(array('ComposerAutoloaderInit53e7e9fbc7f3b93c224f3bd5f4f6ec3e', 'loadClassLoader'));
        // 此处判断为真 所以执行下面的 if 语句
        $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';
            // 调用了 autoload_static.php 中的 ComposerStaticInit 的 getInitializer 方法 并将上面的 $loader 传入了进去。
            call_user_func(\Composer\Autoload\ComposerStaticInit53e7e9fbc7f3b93c224f3bd5f4f6ec3e::getInitializer($loader));
        } else {} // else 不执行 就不复制了。

进入 /vendor/composer/autoload_static.php

<?php

// autoload_static.php @generated by Composer

namespace Composer\Autoload;

class ComposerStaticInit53e7e9fbc7f3b93c224f3bd5f4f6ec3e
{
    public static $files = array ();
    public static $prefixLengthsPsr4 = array ();
    public static $prefixDirsPsr4 = array ();
    public static $prefixesPsr0 = array ();
    public static $classMap = array ();

    // 以上五个变量,暂时没有用到,先折叠了。
    // 上面调用了该方法,功能是修改了$loader 的私有变量
    // 分别将本类(ComposerStaticInit)的四个变量,赋值给了 $loader
    // 这四个变量分别是 $prefixLengthsPsr4, $prefixDirsPsr4, $prefixesPsr0, $classMap
    public static function getInitializer(ClassLoader $loader)
    {
        return \Closure::bind(function () use ($loader) {
            $loader->prefixLengthsPsr4 = ComposerStaticInit53e7e9fbc7f3b93c224f3bd5f4f6ec3e::$prefixLengthsPsr4;
            $loader->prefixDirsPsr4 = ComposerStaticInit53e7e9fbc7f3b93c224f3bd5f4f6ec3e::$prefixDirsPsr4;
            $loader->prefixesPsr0 = ComposerStaticInit53e7e9fbc7f3b93c224f3bd5f4f6ec3e::$prefixesPsr0;
            $loader->classMap = ComposerStaticInit53e7e9fbc7f3b93c224f3bd5f4f6ec3e::$classMap;

        }, null, ClassLoader::class);
    }
}

Closure 的用法实例,可以参考这里 此时 $loader 的四个私有变量值已经改变。

为什么这里不用setVal() 方法呢?比如:

class Foo ()
{
    private $val;

    public function setVal($val)
    {
        $this->val = $val;
    }
}

回到 /vendor/composer/autoload_real.php

        // ...
        if ($useStaticLoader) {
            require_once __DIR__ . '/autoload_static.php';

            call_user_func(\Composer\Autoload\ComposerStaticInit53e7e9fbc7f3b93c224f3bd5f4f6ec3e::getInitializer($loader));
        } else {
        // 没有运行 折叠了。
        // ...
        }
        // 运行到此处了
        // 调用了 register 方法。
        $loader->register(true);

进入 vendor/composer/ClassLoader.php

<?php
namespace Composer\Autoload;

class ClassLoader
{
    // ... 折叠
    /**
     * Registers this instance as an autoloader.
     *
     * @param bool $prepend Whether to prepend the autoloader or not
     */
    // 调用了该方法 注册了 ClassLoader 类,和 loadClass 方法 
    public function register($prepend = false)
    {
        spl_autoload_register(array($this, 'loadClass'), true, $prepend);
    }

    /**
     * Loads the given class or interface.
     *
     * @param  string    $class The name of the class
     * @return bool|null True if loaded, null otherwise
     */
    // 该方法就是根据 $class 查找该变量对应的文件,并引入。
    public function loadClass($class)
    {
        if ($file = $this->findFile($class)) {
            includeFile($file);

            return true;
        }
    }

    // ... 折叠
}

/**
 * Scope isolated include.
 *
 * Prevents access to $this/self from included files.
 */
function includeFile($file)
{
    include $file;
}

回到 /vendor/composer/autoload_real.php

        // ... 折叠
        $loader->register(true);

        if ($useStaticLoader) {
            // 为 $includeFiles 赋值,此时它的值为 ComposerStaticInit::$files 的值
            $includeFiles = Composer\Autoload\ComposerStaticInit53e7e9fbc7f3b93c224f3bd5f4f6ec3e::$files;
        } else {
            // ... 折叠
        }
        foreach ($includeFiles as $fileIdentifier => $file) {
            // 遍历 ComposerStaticInit::$files 调用下面的 composerRequire 方法,目地是将 $files 内的文件全部 require
            // 并且定义一个全局变量,该全局变量,设置为 true
            // 以防止重复引用?
            composerRequire53e7e9fbc7f3b93c224f3bd5f4f6ec3e($fileIdentifier, $file);
        }
        // 返回 $loader

        return $loader;
    }
}

function composerRequire53e7e9fbc7f3b93c224f3bd5f4f6ec3e($fileIdentifier, $file)
{
    if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
        require $file;

        $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
    }
}

此时 autoload.php 运行完毕了,回到 index.php

回到 /public/index.php

<?php

define('LARAVEL_START', microtime(true));
require __DIR__.'/../vendor/autoload.php';

// 运行到此处了。进入该文件
$app = require_once __DIR__.'/../bootstrap/app.php';

// ... 折叠

进入 /bootstrap/app.php

<?php

/*
|--------------------------------------------------------------------------
| Create The Application
|--------------------------------------------------------------------------
|
| The first thing we will do is create a new Laravel application instance
| which serves as the "glue" for all the components of Laravel, and is
| the IoC container for the system binding all of the various parts.
|
*/
// 这里 new 了一个类,进入该文件看看
$app = new Illuminate\Foundation\Application(
    $_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
);
// ... 折叠

这里有个 PHP 7.0 引入的新运算符 ?? 参考文档

<?php
// Example usage for: Null Coalesce Operator
$action = $_POST['action'] ?? 'default';

// The above is identical to this if/else statement
if (isset($_POST['action'])) {
    $action = $_POST['action'];
} else {
    $action = 'default';
}

?>

所以 这里传入的值始是 dirname(__DIR__) 也就是laravel 源码的根目录

$app = new Illuminate\Foundation\Application(
    $_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
);