Laravel源码(流程)解析

2 篇文章 0 订阅

解析index.php

首先我们来看index.php这个人口文件

//为Laravel应用引入了由 Composer 提供的类加载器,这样Laravel应用便无需再手动加载任 何的类。关于Composer,我有时间,专门写一篇文章
require __DIR__.'/../bootstrap/autoload.php';

//启动整个项目
$app = require_once __DIR__.'/../bootstrap/app.php';

接着我们来看看app.php这个文件都做了什么

解析app.php

$app = new Illuminate\Foundation\Application(
    realpath(__DIR__.'/../')
);

$app->singleton(
    Illuminate\Contracts\Http\Kernel::class,
    App\Http\Kernel::class
);

$app->singleton(
    Illuminate\Contracts\Console\Kernel::class,
    App\Console\Kernel::class
);

$app->singleton(
 Illuminate\Contracts\Debug\ExceptionHandler::class,
    App\Exceptions\Handler::class
);

return $app;

首先实例化了Application这个类,接下来我们来看看Application这个类

Application类解读

首先我们看一下Application类的构造函数

    public function __construct($basePath = null)
    {
       //绑定Appliation和Container到instance容器
        $this->registerBaseBindings();

       //注册基础的Service Provider
        $this->registerBaseServiceProviders();

       //注册别名,把一系列key和对应的类名,接口名加入alias属性数组
        $this->registerCoreContainerAliases();

       //注册该应用程序的路径
        if ($basePath) {
            $this->setBasePath($basePath);
        }
    }

registerBaseServiceProviders这个方法注册两个基本的服务提供者EventServiceProvider和RoutingServiceProvider,关于服务提供者,都继承了Illuminate\Support\ServiceProvider这个类,它接受一个 Application 对象作为构造函数参数,存储在实例变量 $app 中。这个抽象类要求你在你的提供者上定义至少一个方法:register。在 register 方法中,你应该 只将事物绑定至 服务容器 之中。永远不要试图在register 方法中注册任何事件侦听器、路由或任何其它功能。

EventServiceProvider解析

首先我们看一下Illuminate\Events\EventServiceProvider的register方法

    public function register()
    {
        $this->app->singleton('events', function ($app) {
            return (new Dispatcher($app))->setQueueResolver(function () use ($app) {
                return $app->make('Illuminate\Contracts\Queue\Factory');
            });
        });
    }

上面方法中将Illuminate\Events\Dispatcher注册了一个单例绑定到了容器中,键名为 events,它负责实现事件的调度。

RoutingServiceProvider解析

再来我们看一下Illuminate\Routing\RoutingServiceProvider的register方法

public function register()
{
    $this->registerRouter();

    $this->registerUrlGenerator();

    $this->registerRedirector();

    $this->registerPsrRequest();

    $this->registerPsrResponse();

    $this->registerResponseFactory();
}

把路由相关的服务(Router, RouterGenerator, Redirector, ResponseFactory)注入到了app主体中


回到app.php

接着app.php又注册了三个单例到容器,分别是http处理核心类(App\Http\Kernel),cli处理核心类(App\Console\Kernel),和异常处理(App\Exceptions\Handler).


回到index.php

//在app.php中 Http\Kernel已经被注册到容器 所以可以通过make调用实例化
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);

调用了\Illuminate\Foundation\Http\Kernel::handle来处理请求
$response = $kernel->handle(
    $request = Illuminate\Http\Request::capture()
);

解析App\Http\Kernel

<?php

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{
    /**
     * 注册应用程序的全局HTTP中间件。
     */
    protected $middleware = [
        \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\VerifyCsrfToken::class,
    ];

    /**
     * 注册应用程序路由中间件。
     */
    protected $routeMiddleware = [
        'authenticate' => \App\Http\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'search' => \App\Http\Middleware\FilterSearchCondition::class,
        'role' => \Zizaco\Entrust\Middleware\EntrustRole::class,
        'permission' => \Zizaco\Entrust\Middleware\EntrustPermission::class,
        'ability' => \Zizaco\Entrust\Middleware\EntrustAbility::class,
        'authorize' => \App\Http\Middleware\Authorize::class,
        'wxAuthenticate' => \App\Http\Middleware\WxAuthenticate::class,
        'wxActivityStat' => \App\Http\Middleware\WxActivityStat::class,
        'wxFollowRequired' => \App\Http\Middleware\WxFollowRequired::class,

    ];
}

该类继承了Illuminate\Foundation\Http\Kernel,我们主要看构造函数和handle方法

__construct方法

    public function __construct(Application $app, Router $router)
    {
        $this->app = $app;
        $this->router = $router;

        foreach ($this->routeMiddleware as $key => $middleware) {
            $router->middleware($key, $middleware);
        }
    }

看构造函数主要功能是注册中间件

handle方法

public function handle($request){
...
$response = $this->sendRequestThroughRouter($request);
...
}


protected function sendRequestThroughRouter($request)
{
//將request类注册到容器
$this->app->instance('request', $request);

Facade::clearResolvedInstance('request');
//完成http请求环境的初始化 下面详解
$this->bootstrap();

//运行中间件(关于中间件下回详解)最后dispatchToRouter解析路由 执行并返回路由结果
return (new Pipeline($this->app))
->send($request)
->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
->then($this->dispatchToRouter());
}



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

protected function bootstrappers()
    {
        return $this->bootstrappers;
    }

Illuminate\Foundation\Application

    /**
     * Run the given array of bootstrap classes.
     *
     * @param  array  $bootstrappers
     * @return void
     */
    public function bootstrapWith(array $bootstrappers)
    {
        $this->hasBeenBootstrapped = true;

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

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

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

由此可见,最终\Illuminate\Foundation\Http\Kernel::bootstrap中通过Application::bootstrapWith完成http请求环境的初始化,具体则是:
•标记Application为已经引导启动状态
•依次启动\Illuminate\Foundation\Http\Kernel::$bootstrappers中的项目

  1. Illuminate\Foundation\Bootstrap\DetectEnvironment解析.env文件,设置应用程序的环境
  2. Illuminate\Foundation\Bootstrap\LoadConfiguration:加载应用程序的配置文件、绑定配置类到容器
  3. Illuminate\Foundation\Bootstrap\ConfigureLogging:绑定日志处理类
  4. Illuminate\Foundation\Bootstrap\HandleExceptions:异常处理
  5. Illuminate\Foundation\Bootstrap\RegisterFacades:Facade模式的应用
  6. Illuminate\Foundation\Bootstrap\RegisterProviders:将服务注册到容器(执行register完成注入)
  7. Illuminate\Foundation\Bootstrap\BootProviders:运行每个服务中的boot方法

回到index.php

//运行Illuminate\Http\Response父类的send方法
$response->send();


//在 HTTP 响应被发送到浏览器之后,调用中间件的terminate()方法
$kernel->terminate($request, $response);

解析Symfony\Component\HttpFoundation\Response的send方法

public function send()
{
//设置请求头
$this->sendHeaders();
//输出内容
$this->sendContent();

if (function_exists('fastcgi_finish_request')) {
fastcgi_finish_request();
} elseif ('cli' !== PHP_SAPI) {
static::closeOutputBuffers(0, true);
}

return $this;
}

至此,larvel解析告一段落,基本流程已经走完

总结

1、引入了由 Composer 提供的类加载器
2、基础启动

  • 绑定Appliation和Container到instance容器
  • 注册基础的Service Provider
  • 注册别名
  • 注册该应用程序的路径

3、 注册http处理核心类(App\Http\Kernel)、cli处理核心类(App\Console\Kernel)和异常处理(App\Exceptions\Handler)

  • 注册中间件
  • 完成http请求环境的初始化
1. Illuminate\Foundation\Bootstrap\DetectEnvironment解析.env文件,设置应用程序的环境
2. Illuminate\Foundation\Bootstrap\LoadConfiguration:加载应用程序的配置文件、绑定配置类到容器
3. Illuminate\Foundation\Bootstrap\ConfigureLogging:绑定日志处理类
4. Illuminate\Foundation\Bootstrap\HandleExceptions:异常处理
5. Illuminate\Foundation\Bootstrap\RegisterFacades:Facade模式的应用
6. Illuminate\Foundation\Bootstrap\RegisterProviders:将服务注册到容器(执行register完成注入)
7. Illuminate\Foundation\Bootstrap\BootProviders:运行每个服务中的boot方法
  • 运行中间件

4、运行Illuminate\Http\Response父类的send方法响应请求
5、在 HTTP 响应被发送到浏览器之后,调用中间件的terminate()方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值