一步步讲解laravel bootstrap启动过程,带你了解每个细节

背景:想知道web.php这个文件是如何被加载运行的

在sendRequestThroughRouter()中会启动一些类

public function bootstrap()
{
    if (! $this->app->hasBeenBootstrapped()) {
        $this->app->bootstrapWith($this->bootstrappers());
    }
}

public function bootstrapWith(array $bootstrappers)
{
    $this->hasBeenBootstrapped = true;
    /*
    $bootstrappers 打印出
    array(6) {
      [0]=>
      string(56) "Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables"
      [1]=>
      string(49) "Illuminate\Foundation\Bootstrap\LoadConfiguration"
      [2]=>
      string(48) "Illuminate\Foundation\Bootstrap\HandleExceptions"
      [3]=>
      string(47) "Illuminate\Foundation\Bootstrap\RegisterFacades"
      [4]=>
      string(49) "Illuminate\Foundation\Bootstrap\RegisterProviders"
      [5]=>
      string(45) "Illuminate\Foundation\Bootstrap\BootProviders"
    }
    */

    foreach ($bootstrappers as $bootstrapper) {
        $this['events']->dispatch('bootstrapping: '.$bootstrapper, [$this]);

        $this->make($bootstrapper)->bootstrap($this);

        $this['events']->dispatch('bootstrapped: '.$bootstrapper, [$this]);
    }
}

代码1

上面会运行6个类,这里举例了RegisterProviders的过程,也就是上面中的第5个

//在代码1中进行bootstrap,这里是Illuminate\Foundation\Bootstrap\RegisterProviders
public function bootstrap(Application $app)
{
    $app->registerConfiguredProviders();
}

//上面RegisterProviders的bootstrap中运行了如下方法
public function registerConfiguredProviders()
{
    //Illuminate里和app里的分开
    $providers = Collection::make($this->config['app.providers'])
                    ->partition(function ($provider) {
                        return Str::startsWith($provider, 'Illuminate\\');
                    });

    //添加一些其它的类文件
    $providers->splice(1, 0, [$this->make(PackageManifest::class)->providers()]);
    //所有的provider,真正去注册 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    (new ProviderRepository($this, new Filesystem, $this->getCachedServicesPath()))
                ->load($providers->collapse()->toArray());
}

//接上面最后一行Illuminate\Foundation\ProviderRepository.php
public function load(array $providers)
{
    //这里foreach的是很多的provider
    foreach ($manifest['eager'] as $provider) {
        $this->app->register($provider);//注册provider,运行每个provider的register方法
    }
}

到这里所有的provider register结束。

上面是Illuminate\Foundation\Bootstrap\RegisterProviders的运行过程
下面是Illuminate\Foundation\Bootstrap\BootProviders的运行过程,在代码1中,这个会最后运行
IIlluminate\Foundation\Bootstrap\BootProviders.php 对app进行了boot

//Illuminate\Foundation\Bootstrap\BootProviders.php
public function bootstrap(Application $app)
{
    $app->boot();
}

//Illuminate\Foundation\Application.php
public function boot()
{
    //对每个service provider进行bootProvider操作
    array_walk($this->serviceProviders, function ($p) {
        $this->bootProvider($p);
    });
}
//对每个provider进行boot操作
protected function bootProvider(ServiceProvider $provider)
{
    if (method_exists($provider, 'boot')) {
        return $this->call([$provider, 'boot']);
    }
}

会自动运行每个provider的boot方法,所以到了这里就能看RouteServiceProvider.php 中的boot方法到底做了什么,因为它也是provider中的一个。

分析route的boot方法,下面是来自不同文件的方法,为了看起来方便,把它们整合到了一起

public function boot()
{
    $this->loadRoutes();

    $this->app->booted(function () {
        $this->app['router']->getRoutes()->refreshNameLookups();
        $this->app['router']->getRoutes()->refreshActionLookups();
    });
}

protected function loadRoutes()
{
    if (method_exists($this, 'map')) {
        $this->app->call([$this, 'map']);
    }
}

public function map()
{
    $this->mapApiRoutes();
    $this->mapWebRoutes();
}

protected function mapWebRoutes()
{
    Route::middleware('jack route web');

    Route::middleware('web')
         ->namespace($this->namespace)
         ->group(base_path('routes/web.php'));
}

到这里就一步步分析了web.php是如何被加载的。也许会疑问group是什么作用,为什么web.php传进了这个group里,继续来研究。。。

其实在Route::middleware('web')是没有middleware这个静态方法的,所以调用的是Illuminate\Routing\Router.php中的__call 这个魔术方法,在这个__call里其实是new 的RouteRegistrar,所以到Illuminate\Routing\RouteRegistrar.php中找group方法。

public function group($callback)
{
    /*
     * array(2) {
          ["middleware"]=>
          array(1) {
            [0]=>
            string(3) "web"
          }
          ["namespace"]=>
          string(20) "App\Http\Controllers"
        }
        $callback就是group里传入的文件路径
     * */


    $this->router->group($this->attributes, $callback);
}

//Illuminate\Routing\Router.php
public function group(array $attributes, $routes)
{
    //放入到$this->groupStack中
    $this->updateGroupStack($attributes);

    $this->loadRoutes($routes);

    array_pop($this->groupStack);
}

protected function loadRoutes($routes)
{
    if ($routes instanceof Closure) {
        $routes($this);
    } else {
        //传入web.php的路径,D:\sites\laravel\routes\web.php
        (new RouteFileRegistrar($this))->register($routes);
    }
}

public function register($routes)
{
    $router = $this->router;

    require $routes;//这里就把web.php require进来了
}

到这里解释了web.php是如何被加载进来的 : )

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,324评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,356评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,328评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,147评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,160评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,115评论 1 296
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,025评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,867评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,307评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,528评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,688评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,409评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,001评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,657评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,811评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,685评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,573评论 2 353

推荐阅读更多精彩内容