美文网首页
Laravel5.4 启动探索

Laravel5.4 启动探索

作者: 爱折腾的傻小子 | 来源:发表于2018-10-29 11:01 被阅读5次
    index.php 入口文件
    <?php
    
    /**
     * Laravel - A PHP Framework For Web Artisans
     *
     * @package  Laravel
     * @author   Taylor Otwell <taylor@laravel.com>
     */
    
    /*
    |--------------------------------------------------------------------------
    | 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.
    |
    */
    # 自动加载 更多需要配合参考 composer.json 文件 和 源代码
    require __DIR__.'/../bootstrap/autoload.php';
    
    /*
    |--------------------------------------------------------------------------
    | 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.
    |
    */
    # 框架启动 返回一个 Application 实例对象 (包括注入容器等)
    $app = require_once __DIR__.'/../bootstrap/app.php';
    
    /*
    |--------------------------------------------------------------------------
    | 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.
    |
    */
    # 从容器中解析http请求实例(聚焦make解析容器实例--反射相关知识)
    $kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
    
    # 处理中间件、路由到控制器、注入服务器提供等操作 返回一个响应实例(这里是启动整个框架最重要地方)
    $response = $kernel->handle(
        # 请求数据处理 注入$request 
        $request = Illuminate\Http\Request::capture()
    );
    # 发送响应到客户端
    $response->send();
    
    # 响应结束,调用中间件的terminate方法处理部分事情
    $kernel->terminate($request, $response);
    
    自动加载初窥
    • 自动加载最主要代码(来自vendor/composer目录下的自动加载文件里)
    <?php
    
    // autoload_real.php @generated by Composer
    
    class ComposerAutoloaderInit4b1cb372bdf84554786fa050e282ae68
    {
        private static $loader;
    
        public static function loadClassLoader($class)
        {
            if ('Composer\Autoload\ClassLoader' === $class) {
                require __DIR__ . '/ClassLoader.php';
            }
        }
    
        # 自动加载首先被调用的方法 (注入自动加载器等)
        public static function getLoader()
        {
            # 如果当前自动加载实例对象已被创建就返回该对象
            if (null !== self::$loader) {
                return self::$loader;
            }
            # apl_autoload_register 自动加载器 加载指定类的指定方法(参数一)
            # 注入失败抛出异常(参数二)
            # 添加到队列之首(参数三)
            spl_autoload_register(array('ComposerAutoloaderInit4b1cb372bdf84554786fa050e282ae68', 'loadClassLoader'), true, true);
            # 创建一个ClassLoader实例,会调用已注册的loadClassLoader方法加载对应的类文件
            self::$loader = $loader = new \Composer\Autoload\ClassLoader();
            # 注销自动加载器指定方法
            spl_autoload_unregister(array('ComposerAutoloaderInit4b1cb372bdf84554786fa050e282ae68', 'loadClassLoader'));
            # 判断当前系统环境 
            # PHP_VERSION 当前php版本5.6或以上
            # 当前是否HHVM中
            # zend_loader_file_encoded() 当前文件是否zend加密(就是当前问价是否被编译成二进制码)
            $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
            # 自动加载
            if ($useStaticLoader) {
                # 引入autoload_static.php 文件
                # 该文件主要是管理需要加载类的所在位置的一些配置文件信息
                # 部分属性配置由composer install执行时,被追加或写入到指定属性中
                require_once __DIR__ . '/autoload_static.php';
                # 执行一个回调函数调用(主要:ClassLoader生成的一个实例对象属性添加值)
                call_user_func(\Composer\Autoload\ComposerStaticInit4b1cb372bdf84554786fa050e282ae68::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);
    
            # 引入files属性里面的辅助文件 使辅助方法可用
            if ($useStaticLoader) {
                $includeFiles = Composer\Autoload\ComposerStaticInit4b1cb372bdf84554786fa050e282ae68::$files;
            } else {
                $includeFiles = require __DIR__ . '/autoload_files.php';
            }
            foreach ($includeFiles as $fileIdentifier => $file) {
                composerRequire4b1cb372bdf84554786fa050e282ae68($fileIdentifier, $file);
            }
            # 上面辅助函数文件引入就能调用app()类型的函数了 虽然里面什么都没有
    
            return $loader;
        }
    }
    
    function composerRequire4b1cb372bdf84554786fa050e282ae68($fileIdentifier, $file)
    {
        if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
            require $file;
    
            $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
        }
    }
    
    • 参看一下ComposerStaticInit4b1cb372bdf84554786fa050e282ae68类文件
    # 由于文件数据较多,不做详细粘贴
    files 属性:里面存储加载包时,所自定义的一些函数文件(如:laravel自带的辅助函数文件一样)
    prefixLengthsPsr4 属性:保存的是一些类文件的命名空间名称(该名称长度大小)
    prefixDirsPsr4 属性:保存的是上面命名空间下的一些src文件所在路径
    prefixesPsr0 属性:保存的是命名空间和该命名空间下的一些文件src路径
    classMap 属性:保存的是类的映射(比如说一些控制器的映射路径等)
    
    启动框架服务
    • $app = require_once __DIR__.'/../bootstrap/app.php' 引入框架文件
    • 这里主要注入Application应用类并创建服务器容器,绑定一些服务在容器中
    <?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.
    |
    */
    # 创建一个app应用实例(参看下面代码,参看构造器创建应用初始化)
    $app = new Illuminate\Foundation\Application(
        realpath(__DIR__.'/../')
    );
    
    /*
    |--------------------------------------------------------------------------
    | Bind Important Interfaces
    |--------------------------------------------------------------------------
    |
    | Next, we need to bind some important interfaces into the container so
    | we will be able to resolve them when needed. The kernels serve the
    | incoming requests to this application from both the web and CLI.
    |
    */
    # 向容器中注入 Http 请求 
    $app->singleton(
        Illuminate\Contracts\Http\Kernel::class,
        App\Http\Kernel::class
    );
    # 向容器中注入控制台请求(用于 php artisan list 命令使用)
    $app->singleton(
        Illuminate\Contracts\Console\Kernel::class,
        App\Console\Kernel::class
    );
    # 向容器中注入异常处理机制
    $app->singleton(
        Illuminate\Contracts\Debug\ExceptionHandler::class,
        App\Exceptions\Handler::class
    );
    
    /*
    |--------------------------------------------------------------------------
    | Return The Application
    |--------------------------------------------------------------------------
    |
    | This script returns the application instance. The instance is given to
    | the calling script so we can separate the building of the instances
    | from the actual running of the application and sending responses.
    |
    */
    
    return $app;
    
    • Application.php 文件构造器级相关方法
    /**
         * Create a new Illuminate application instance.
         *
         * @param  string|null  $basePath
         * @return void
         */
        public function __construct($basePath = null)
        {
            if ($basePath) {
                # 绑定一些文件路径到服务器容器(参看源码)
                $this->setBasePath($basePath);
            }
            # 给容器Container注入Application实例对象并返回(Container是一个静态类)
            # 绑定app、Container::class到容器为Application实例对象(app()辅助函数可从容器中解析服务)
            $this->registerBaseBindings();
            # 启动一些基本服务(绑定一些实例在服务器容器中)
            # 注册事件队列服务 events 绑定队列在容器
            # 注册日志服务 log 绑定日志到容器
            # 注册一系列路由服务 绑定路由或重定向或响应或请求到容器中
            $this->registerBaseServiceProviders();
            # 应用中注入核心类别名(如app、session等别名指向类文件或接口文件|此处并未注册实例对象app('config')这样还是不能从容器中被解析)
            $this->registerCoreContainerAliases();
            # ~ 这里框架应用实例创建完毕
        }
    
    • 聚焦 $app->make() 解析容器实例
    /**
         * Resolve the given type from the container.
         *
         * (Overriding Container::make)
         *
         * @param  string  $abstract
         * @return mixed
         */
        public function make($abstract)
        {
            # 获取别名
            $abstract = $this->getAlias($abstract);
            # 是否延迟加载(参看服务提供者延迟加载文档)
            if (isset($this->deferredServices[$abstract])) {
                # 服务容器注入被延迟加载,在调用服务时执行当前服务提供者的register()方法(先)和boot()方法(后)
                $this->loadDeferredProvider($abstract);
            }
            # 调用父类make()方法 从容器中解析
            return parent::make($abstract);
        }
    
    • Container make() 方法
        /**
         * Resolve the given type from the container.
         *
         * @param  string  $abstract
         * @return mixed
         */
        public function make($abstract)
        {
            return $this->resolve($abstract);
        }
        /**
         * Resolve the given type from the container.
         *
         * @param  string  $abstract
         * @param  array  $parameters
         * @return mixed
         */
        protected function resolve($abstract, $parameters = [])
        {
            $abstract = $this->getAlias($abstract);
    
            $needsContextualBuild = ! empty($parameters) || ! is_null(
                $this->getContextualConcrete($abstract)
            );
    
            // If an instance of the type is currently being managed as a singleton we'll
            // just return an existing instance instead of instantiating new instances
            // so the developer can keep using the same objects instance every time.
            if (isset($this->instances[$abstract]) && ! $needsContextualBuild) {
                return $this->instances[$abstract];
            }
    
            $this->with[] = $parameters;
    
            $concrete = $this->getConcrete($abstract);
    
            // We're ready to instantiate an instance of the concrete type registered for
            // the binding. This will instantiate the types, as well as resolve any of
            // its "nested" dependencies recursively until all have gotten resolved.
            if ($this->isBuildable($concrete, $abstract)) {
                # 解析对象 - 使用反射相关知识
                $object = $this->build($concrete);
            } else {
                $object = $this->make($concrete);
            }
    
            // If we defined any extenders for this type, we'll need to spin through them
            // and apply them to the object being built. This allows for the extension
            // of services, such as changing configuration or decorating the object.
            foreach ($this->getExtenders($abstract) as $extender) {
                $object = $extender($object, $this);
            }
    
            // If the requested type is registered as a singleton we'll want to cache off
            // the instances in "memory" so we can return it later without creating an
            // entirely new instance of an object on each subsequent request for it.
            if ($this->isShared($abstract) && ! $needsContextualBuild) {
                $this->instances[$abstract] = $object;
            }
    
            $this->fireResolvingCallbacks($abstract, $object);
    
            // Before returning, we will also set the resolved flag to "true" and pop off
            // the parameter overrides for this build. After those two things are done
            // we will be ready to return back the fully constructed class instance.
            $this->resolved[$abstract] = true;
    
            array_pop($this->with);
    
            return $object;
        }
    
    • 框架的启动请求 待续......

    相关文章

      网友评论

          本文标题:Laravel5.4 启动探索

          本文链接:https://www.haomeiwen.com/subject/okcpmxtx.html