• laravel生命周期超细腻


    前言

    着手AllInOne项目之前,把laravel项目运行生命周期研究了一下

    入口文件:index.php文件(贴关键代码)

    $app = require_once __DIR__.'/../bootstrap/app.php';
    
    • 1

    引入app.php文件。实例化Application类

    Application类继承Container,Container统称容器,实质就是把一些类,闭包赋值到类的对应的属性上

    	//vendor/laravel/framework/src/Illuminate/Foundation/Application.php
    	
        public function __construct($basePath = null)
        {
    
            if ($basePath) {
                $this->setBasePath($basePath);
            }
            $this->registerBaseBindings(); 
    
            $this->registerBaseServiceProviders(); 
    
    
    
            $this->registerCoreContainerAliases(); 
    
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    t h i s − > s e t B a s e P a t h ( this->setBasePath( this>setBasePath(basePath); 绑定一些基础属性
    $this->registerBaseBindings(); 挂载到容器上bindings属性一些地址映射
    $this->registerBaseServiceProviders(); //单例挂载到bindings 一些服务提供者

    对应方法

      protected function registerBaseServiceProviders()
        {
            $this->register(new EventServiceProvider($this));
            $this->register(new LogServiceProvider($this));
            $this->register(new RoutingServiceProvider($this)); //挂载路由
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    $app->singleton(
        Illuminate\Contracts\Http\Kernel::class,
        App\Http\Kernel::class
    ); //绑定http请求处理程序
    
    $app->singleton(
        Illuminate\Contracts\Console\Kernel::class,
        App\Console\Kernel::class
    );//绑定命令行的一些类
    
    $app->singleton(
        Illuminate\Contracts\Debug\ExceptionHandler::class,
        App\Exceptions\Handler::class
    );//绑定处理异常的一些类
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    绑定到容器 instances属性上

    回到index.php文件

    $kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
    //var_dump(Illuminate\Http\Request::capture());
    $response = $kernel->handle(
        $request = Illuminate\Http\Request::capture()
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5

    1.解析绑定到容器上的实例化的类
    2.解析请求

    handle方法

        /**
         * Handle an incoming HTTP request.
         *
         * @param  \Illuminate\Http\Request  $request
         * @return \Illuminate\Http\Response
         */
        public function handle($request)
        {
            try {
                $request->enableHttpMethodParameterOverride();
    
                $response = $this->sendRequestThroughRouter($request);
            } catch (Exception $e) {
                $this->reportException($e);
    
                $response = $this->renderException($request, $e);
            } catch (Throwable $e) {
                $this->reportException($e = new FatalThrowableError($e));
    
                $response = $this->renderException($request, $e);
            }
    
            $this->app['events']->dispatch(
                new Events\RequestHandled($request, $response)
            );
    
            return $response;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    关键代码:

    $response = t h i s − > s e n d R e q u e s t T h r o u g h R o u t e r ( this->sendRequestThroughRouter( this>sendRequestThroughRouter(request);

    送往管道处理

        /**
         * Send the given request through the middleware / router.
         *
         * @param  \Illuminate\Http\Request  $request
         * @return \Illuminate\Http\Response
         */
        protected function sendRequestThroughRouter($request)
        {
            $this->app->instance('request', $request);
    
            Facade::clearResolvedInstance('request');
    
            $this->bootstrap();
    
            return (new Pipeline($this->app))
                        ->send($request)
                        ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
                        ->then($this->dispatchToRouter());
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    关键代码:

    $this->bootstrap();

    这里先进行服务提供者解析处理,接着往下追

        /**
         * Bootstrap the application for HTTP requests.
         *
         * @return void
         */
        public function bootstrap()
        {
    
    //var_dump($this->bootstrappers());
            if (! $this->app->hasBeenBootstrapped()) {
                $this->app->bootstrapWith($this->bootstrappers());
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    关键代码:

    t h i s − > a p p − > b o o t s t r a p W i t h ( this->app->bootstrapWith( this>app>bootstrapWith(this->bootstrappers());

        /**
         * Run the given array of bootstrap classes.
         *
         * @param  string[]  $bootstrappers
         * @return void
         */
        public function bootstrapWith(array $bootstrappers)
        {
    
            $this->hasBeenBootstrapped = true;
    
            foreach ($bootstrappers as $bootstrapper) {
                $this['events']->dispatch('bootstrapping: '.$bootstrapper, [$this]);
    
                $this->make($bootstrapper)->bootstrap($this);
    
                $this['events']->dispatch('bootstrapped: '.$bootstrapper, [$this]);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    关键代码:

    t h i s − > m a k e ( this->make( this>make(bootstrapper)->bootstrap($this);
    执行服务提供者的 Register方法 \Illuminate\Foundation\Bootstrap\RegisterProviders::class,
    执行服务提供者的 boot方法 \Illuminate\Foundation\Bootstrap\BootProviders::class,

     /**
         * Bootstrap the given application.
         *
         * @param  \Illuminate\Contracts\Foundation\Application  $app
         * @return void
         */
        public function bootstrap(Application $app)
        {
            $app->registerConfiguredProviders();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
        /**
         * Register all of the configured providers.
         *
         * @return void
         */
        public function registerConfiguredProviders()
        {
            $providers = Collection::make($this->config['app.providers'])
                            ->partition(function ($provider) {
                                return Str::startsWith($provider, 'Illuminate\\');
                            });
    
            $providers->splice(1, 0, [$this->make(PackageManifest::class)->providers()]);
    
            (new ProviderRepository($this, new Filesystem, $this->getCachedServicesPath()))
                        ->load($providers->collapse()->toArray());
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    关键代码:

    (new ProviderRepository($this, new Filesystem, t h i s − > g e t C a c h e d S e r v i c e s P a t h ( ) ) ) − > l o a d ( this->getCachedServicesPath())) ->load( this>getCachedServicesPath()))>load(providers->collapse()->toArray());

    到服务提供仓库去执行

       /**
         * Register the application service providers.
         *
         * @param  array  $providers
         * @return void
         */
        public function load(array $providers)
        {
            $manifest = $this->loadManifest();
    
            // First we will load the service manifest, which contains information on all
            // service providers registered with the application and which services it
            // provides. This is used to know which services are "deferred" loaders.
            if ($this->shouldRecompile($manifest, $providers)) {
                $manifest = $this->compileManifest($providers);
            }
    
            // Next, we will register events to load the providers for each of the events
            // that it has requested. This allows the service provider to defer itself
            // while still getting automatically loaded when a certain event occurs.
            foreach ($manifest['when'] as $provider => $events) {
                $this->registerLoadEvents($provider, $events);
            }
    
            // We will go ahead and register all of the eagerly loaded providers with the
            // application so their services can be registered with the application as
            // a provided service. Then we will set the deferred service list on it.
            foreach ($manifest['eager'] as $provider) {
                $this->app->register($provider);
            }
    
            $this->app->addDeferredServices($manifest['deferred']);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    关键代码:

    foreach ($manifest[‘eager’] as $provider) {
    t h i s − > a p p − > r e g i s t e r ( this->app->register( this>app>register(provider);
    }

    最后回到
    vendor/laravel/framework/src/Illuminate/Foundation/Application.php中执行register方法

        /**
         * Register a service provider with the application.
         *
         * @param  \Illuminate\Support\ServiceProvider|string  $provider
         * @param  bool   $force
         * @return \Illuminate\Support\ServiceProvider
         */
        public function register($provider, $force = false)
        {
            if (($registered = $this->getProvider($provider)) && ! $force) {
                return $registered;
            }
    
            // If the given "provider" is a string, we will resolve it, passing in the
            // application instance automatically for the developer. This is simply
            // a more convenient way of specifying your service provider classes.
            if (is_string($provider)) {
                $provider = $this->resolveProvider($provider);
            }
    
            $provider->register();
    
            // If there are bindings / singletons set as properties on the provider we
            // will spin through them and register them with the application, which
            // serves as a convenience layer while registering a lot of bindings.
            if (property_exists($provider, 'bindings')) {
                foreach ($provider->bindings as $key => $value) {
                    $this->bind($key, $value);
                }
            }
    
            if (property_exists($provider, 'singletons')) {
                foreach ($provider->singletons as $key => $value) {
                    $this->singleton($key, $value);
                }
            }
    
            $this->markAsRegistered($provider);
    
            // If the application has already booted, we will call this boot method on
            // the provider class so it has an opportunity to do its boot logic and
            // will be ready for any usage by this developer's application logic.
            if ($this->isBooted()) {
                $this->bootProvider($provider);
            }
    
            return $provider;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    关键代码:

    if (is_string($provider)) {
    $provider = t h i s − > r e s o l v e P r o v i d e r ( this->resolveProvider( this>resolveProvider(provider);
    }
    $provider->register();

    boot方法同思想

       /**
         * Boot the application's service providers.
         *
         * @return void
         */
        public function boot()
        {
            if ($this->isBooted()) {
                return;
            }
    
            // Once the application has booted we will also fire some "booted" callbacks
            // for any listeners that need to do work after this initial booting gets
            // finished. This is useful when ordering the boot-up processes we run.
            $this->fireAppCallbacks($this->bootingCallbacks);
    
            array_walk($this->serviceProviders, function ($p) {
                $this->bootProvider($p);
            });
    
            $this->booted = true;
    
            $this->fireAppCallbacks($this->bootedCallbacks);
        }
      /**
         * Boot the given service provider.
         *
         * @param  \Illuminate\Support\ServiceProvider  $provider
         * @return mixed
         */
        protected function bootProvider(ServiceProvider $provider)
        {
            if (method_exists($provider, 'boot')) {
                return $this->call([$provider, 'boot']);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    回到 vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php sendRequestThroughRouter方法

      /**
         * Send the given request through the middleware / router.
         *
         * @param  \Illuminate\Http\Request  $request
         * @return \Illuminate\Http\Response
         */
        protected function sendRequestThroughRouter($request)
        {
            $this->app->instance('request', $request);
    
            Facade::clearResolvedInstance('request');
    
            $this->bootstrap();
    
            return (new Pipeline($this->app))
                        ->send($request)
                        ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
                        ->then($this->dispatchToRouter());
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    关键代码:
    这边就是处理中间件和分发路由了

    return (new Pipeline( t h i s − > a p p ) ) − > s e n d ( this->app)) ->send( this>app))>send(request)
    ->through($this->app->shouldSkipMiddleware() ? [] : t h i s − > m i d d l e w a r e ) − > t h e n ( this->middleware) ->then( this>middleware)>then(this->dispatchToRouter());

    待续…
    有错误的地方留言指正

  • 相关阅读:
    Jenkins | 流水线构建使用expect免密交互时卡住,直接退出
    git入门教程
    code blocks使用集
    Java根据excel模版导出Excel(easyexcel、poi)——含项目测试例子拿来即用
    vue之$emit返回值
    14种主流的RTOS 单片机操作系统~来学!
    Android 11.0 禁止二次展开QuickQSPanel设置下拉QSPanel高度
    【Github】不支持RSA密钥与SHA-1,使用github token
    [SystemC]SystemC Hierarchical Channels
    Postgresql运维信息(一)
  • 原文地址:https://blog.csdn.net/qq_39586877/article/details/128148771