我独自走进 Laravel5.5 的❤(一)

记录这个经历不是为了说我多厉害,多牛逼,而是为了能够加深自己对所学知识的理解。如果可以帮助到别人学习这个框架的话,小生不胜荣幸。

关于 laravel 的教程很多,我也是通过大量阅读别人写的教程对 laravel 有了一个比较表面的认识。我也不打算把这个当做教程来写,因为我没写过教程,不知道怎么写,而且我个人是比较随意的,请原谅。

既然我是走进去的,就把我当做apache吧,我看到的第一个文件应该是项目中 public 的 index.php 文件。

1.

define('LARAVEL_START', microtime(true));
解读:在运行时定义一个常量 LARAVEL_START 为当前 Unix 时间戳。

2.

require __DIR__.'/../vendor/autoload.php';
解读:引入一个自动加载器

2.1进入到 autoload.php 中

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

return ComposerAutoloaderInit94ec56b468e10706582fb576e66d9831::getLoader();
解读:从 autoload_real.php 中引入自加载入口 getLoader

public static function getLoader()
{
    //如果 $loader 非空,返回 $loader
    if (null !== self::$loader) {
        return self::$loader;
    }

    //spl_autoload_register:注册指定的函数 loadClassLoader 作为__autoload的实现, throw:抛出异常,prepend:添加到队列之首
    spl_autoload_register(array('ComposerAutoloaderInit94ec56b468e10706582fb576e66d9831', 'loadClassLoader'), true, true);
    // 创建 \Composer\Autoload\ClassLoader() 对象,并对象化类属性 $loader
    self::$loader = $loader = new \Composer\Autoload\ClassLoader();
    // 注销已注册的指定的__autoload()函数loadClassLoader
    spl_autoload_unregister(array('ComposerAutoloaderInit94ec56b468e10706582fb576e66d9831', 'loadClassLoader'));

    // 判断 php 版本是否大于5.6,且没有定义 HHVM 版本(一个高性能 PHP 执行引擎,类似于 apache ),且 (不存在函数 zend_loader_file_encoded 或未执行 zend_loader_file_encoded )
    $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
    if ($useStaticLoader) {
        // 加载 autoload_static.php 的 ComposerStaticInit94ec56b468e10706582fb576e66d9831 类,一个静态信息文件,包含了需要自动加载的files路径、psr 规范信息、laravel 框架类的路径
        require_once __DIR__ . '/autoload_static.php';

        //执行 ComposerStaticInit94ec56b468e10706582fb576e66d9831 类中的 getInitializer 静态函数。call_user_func:运行作为第一个参数的回调函数,如果执行失败返回 false,避免发生错误
        /**
         public static function getInitializer(ClassLoader $loader)
        {
        return \Closure::bind(function () use ($loader) {
        $loader->prefixLengthsPsr4 = ComposerStaticInit94ec56b468e10706582fb576e66d9831::$prefixLengthsPsr4;
        $loader->prefixDirsPsr4 = ComposerStaticInit94ec56b468e10706582fb576e66d9831::$prefixDirsPsr4;
        $loader->prefixesPsr0 = ComposerStaticInit94ec56b468e10706582fb576e66d9831::$prefixesPsr0;
        $loader->classMap = ComposerStaticInit94ec56b468e10706582fb576e66d9831::$classMap;

        }, null, ClassLoader::class);
        }
         */
        // getInitializer 其实就是在返回 files 路径、psr 规范信息、laravel 框架类的路径
        call_user_func(\Composer\Autoload\ComposerStaticInit94ec56b468e10706582fb576e66d9831::getInitializer($loader));
    } else {
        //加载 autoload_namespaces.php,返回符合 prs0 自加载插件的命名空间-路径数组
        $map = require __DIR__ . '/autoload_namespaces.php';
        foreach ($map as $namespace => $path) {
            //向 $loader 添加自加载插件
            $loader->set($namespace, $path);
        }

        //加载 autoload_psr4.php,返回符合 prs4 自加载插件的命名空间-路径数组
        $map = require __DIR__ . '/autoload_psr4.php';
        foreach ($map as $namespace => $path) {
            //向 $loader 添加自加载插件
            $loader->setPsr4($namespace, $path);
        }

        //加载 autoload_classmap.php,返回各种需自加载类的命名空间-路径数组
        $classMap = require __DIR__ . '/autoload_classmap.php';
        if ($classMap) {
            //向 $loader 添加自加载类
            $loader->addClassMap($classMap);
        }
    }

    // 预加载 autoloader
    $loader->register(true);

    // 加载框架文件
    if ($useStaticLoader) {
        $includeFiles = Composer\Autoload\ComposerStaticInit94ec56b468e10706582fb576e66d9831::$files;
    } else {
        $includeFiles = require __DIR__ . '/autoload_files.php';
    }
    foreach ($includeFiles as $fileIdentifier => $file) {
        composerRequire94ec56b468e10706582fb576e66d9831($fileIdentifier, $file);
    }

    return $loader;
}

解读:查看代码注释

3.

$app = require_once __DIR__.'/../bootstrap/app.php';
解读:引入laravel框架实例

4.


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

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

$response->send();

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

解读:启动laravel应用与 http 交互,完成 http 请求和响应

/**
     * Resolve the given type from the container.
     * 映射指定类型的容器
     * (Overriding Container::make)
     *
     * @param  string  $abstract
     * @param  array  $parameters
     * @return mixed
     */
    public function make($abstract, array $parameters = [])
    {
        $abstract = $this->getAlias($abstract);

        if (isset($this->deferredServices[$abstract]) && ! isset($this->instances[$abstract])) {
            $this->loadDeferredProvider($abstract);
        }

        return parent::make($abstract, $parameters);
    }

// Illuminate\Container\Container::class
/**
     * Get the alias for an abstract if available.
     * 获取可信赖的类组
     * @param  string  $abstract
     * @return string
     *
     * @throws \LogicException
     */
    public function getAlias($abstract)
    {
        if (! isset($this->aliases[$abstract])) {
            return $abstract;
        }

        if ($this->aliases[$abstract] === $abstract) {
            throw new LogicException("[{$abstract}] is aliased to itself.");
        }

        return $this->getAlias($this->aliases[$abstract]);
    }

    // Illuminate\Foundation\Application::class
    public function loadDeferredProvider($service)
    {
        if (! isset($this->deferredServices[$service])) {
            return;
        }

        $provider = $this->deferredServices[$service];

        // If the service provider has not already been loaded and registered we can
        // register it with the application and remove the service from this list
        // of deferred services, since it will already be loaded on subsequent.
        // 当服务提供者即将被加载,如果服务提供者还没有被加载和注册,
        // 我们可以在这个应用中注册它,并且去除
        // 这个列表中已经缓存的服务
        if (! isset($this->loadedProviders[$provider])) {
            $this->registerDeferredProvider($provider, $service);
        }
    }

    public function registerDeferredProvider($provider, $service = null)
    {
        // Once the provider that provides the deferred service has been registered we
        // will remove it from our local list of the deferred services with related
        // providers so that this container does not try to resolve it out again.
        // 一旦服务提供者提供被注册的缓存的服务,我们将从我们本地缓存的服务列表中去除它和
        //与它相关联的服务提供者,如此这个容器就不会再尝试映射它。
        if ($service) {
            unset($this->deferredServices[$service]);
        }

        $this->register($instance = new $provider($this));

        if (! $this->booted) {
            $this->booting(function () use ($instance) {
                $this->bootProvider($instance);
            });
        }
    }
本作品采用《CC 协议》,转载必须注明作者和本文链接
本帖由系统于 3年前 自动加精
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 3
Summer

源码阅读的思路不错

3年前 评论
LeoYao

@Summer 谢谢~倍感鼓舞

3年前 评论
wanghan

引入autoload.php时候,为什么不用require_once呢

2年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!