2021-06-26(记录)

前言

阅读了一段时间的laravel源码,现将一个成果做一个输出。主要是围绕laavel生命周期展开。



1.加载composer

2.创建app容器和绑定内核到app容器中

代码如下(示例):

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

2.1 创建app容器

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

public function __construct($basePath = null)
{
	//设置基本路径
	if ($basePath) {
	$this->setBasePath($basePath);
	}
	 //基本注册绑定到容器中
	$this->registerBaseBindings();
	//3个服务(events/logs/route)绑定到容器中
	$this->registerBaseServiceProviders();
	//为核心类设置别名
	$this->registerCoreContainerAliases();
}

2.2 内核绑定app容器

//将http内核绑定到app容器中

$app->singleton(
    Illuminate\Contracts\Http\Kernel::class,
    App\Http\Kernel::class
);
//将console内核绑定到app容器中
$app->singleton(
    Illuminate\Contracts\Console\Kernel::class,
    App\Console\Kernel::class
);
//绑定异常处理
$app->singleton(
    Illuminate\Contracts\Debug\ExceptionHandler::class,
    App\Exceptions\Handler::class
);

3.解析内核

$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
public function __construct(Application $app, Router $router)
{
    //app容器
    $this->app = $app;
    //路由器
    $this->router = $router;

    $router->middlewarePriority = $this->middlewarePriority;

    //中间件数组 封装为一个数组
    foreach ($this->middlewareGroups as $key => $middleware) {
        $router->middlewareGroup($key, $middleware);
    }

    //路由中间件 封装为一个数组
    foreach ($this->routeMiddleware as $key => $middleware) {
        $router->aliasMiddleware($key, $middleware);
    }
}




public function middlewareGroup($name, array $middleware)
{
    $this->middlewareGroups[$name] = $middleware;

    return $this;
}


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

4.处理http请求

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

4.1 获取http请求实例

//

public static function capture()
{
    static::enableHttpMethodParameterOverride();
    
    
    //从symfony里获取一个请求实例,创建一个基本的请求
    return static::createFromBase(SymfonyRequest::createFromGlobals());
}


//symfony实例获取一个laravel请求报文
public static function createFromBase(SymfonyRequest $request)
{
    if ($request instanceof static) {
        return $request;
    }

    $content = $request->content;

    $request = (new static)->duplicate(
        $request->query->all(), $request->request->all(), $request->attributes->all(),
        $request->cookies->all(), $request->files->all(), $request->server->all()
    );

    $request->content = $content;

    $request->request = $request->getInputSource();

    return $request;
}

4.1.1 symfony组件处理请求参数

public static function createFromGlobals()
{

    $request = self::createRequestFromFactory($_GET, $_POST, [], $_COOKIE, $_FILES, $_SERVER);

    if (0 === strpos($request->headers->get('CONTENT_TYPE', ''), 'application/x-www-form-urlencoded')
        && \in_array(strtoupper($request->server->get('REQUEST_METHOD', 'GET')), ['PUT', 'DELETE', 'PATCH'])
    ) {
        parse_str($request->getContent(), $data);
        $request->request = new ParameterBag($data);
    }

    return $request;
}

//实例化当前类,把php预定义变量传入

private static function createRequestFromFactory(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null): self
{
    if (self::$requestFactory) {
        $request = (self::$requestFactory)($query, $request, $attributes, $cookies, $files, $server, $content);

        if (!$request instanceof self) {
            throw new \LogicException('The Request factory must return an instance of Symfony\Component\HttpFoundation\Request.');
        }

        return $request;
    }

    return new static($query, $request, $attributes, $cookies, $files, $server, $content);
}

//构造函数

public function __construct(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null)
{
    $this->initialize($query, $request, $attributes, $cookies, $files, $server, $content);
}

//给属性赋值
public function initialize(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null)
{
    $this->request = new ParameterBag($request);
    $this->query = new ParameterBag($query);
    $this->attributes = new ParameterBag($attributes);
    $this->cookies = new ParameterBag($cookies);
    $this->files = new FileBag($files);
    $this->server = new ServerBag($server);
    $this->headers = new HeaderBag($this->server->getHeaders());

    $this->content = $content;
    $this->languages = null;
    $this->charsets = null;
    $this->encodings = null;
    $this->acceptableContentTypes = null;
    $this->pathInfo = null;
    $this->requestUri = null;
    $this->baseUrl = null;
    $this->basePath = null;
    $this->method = null;
    $this->format = null;
}

4.2 handle 请求实例

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;
}


protected function sendRequestThroughRouter($request)
{
   //绑定请求到app容器中
    $this->app->instance('request', $request);

   //清除之前$request实例
    Facade::clearResolvedInstance('request');

    //启动引导程序
    $this->bootstrap();

            //管道创建(Pipeline)
    return (new Pipeline($this->app))
               //将请求传入管道
                ->send($request)
                //执行中间件处理
                ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
               //实际处理
                ->then($this->dispatchToRouter());
}

4.2.1 请求在管道中的实际处理

protected function dispatchToRouter()
{
    return function ($request) {
        $this->app->instance('request', $request);

        return $this->router->dispatch($request);
    };
}

Illuminate\Routing\Router


public function dispatch(Request $request)
{
    $this->currentRequest = $request;

    return $this->dispatchToRoute($request);
}
 
public function dispatchToRoute(Request $request)
{
    return $this->runRoute($request, $this->findRoute($request));
}


//根据请求报文查找匹配的路由
protected function findRoute($request)
{
    $this->current = $route = $this->routes->match($request);

    $this->container->instance(Route::class, $route);

    return $route;
}


//通过一个实例栈运行给定的路由

protected function runRoute(Request $request, Route $route)
{
    $request->setRouteResolver(function () use ($route) {
        return $route;
    });

    $this->events->dispatch(new Events\RouteMatched($route, $request));

    return $this->prepareResponse($request,
        $this->runRouteWithinStack($route, $request)
    );
}

//返回响应结果

protected function runRouteWithinStack(Route $route, Request $request)
{
    $shouldSkipMiddleware = $this->container->bound('middleware.disable') &&
                            $this->container->make('middleware.disable') === true;

    $middleware = $shouldSkipMiddleware ? [] : $this->gatherRouteMiddleware($route);

    return (new Pipeline($this->container))
                    ->send($request)
                    ->through($middleware)
                    ->then(function ($request) use ($route) {
                        return $this->prepareResponse(
                            $request, $route->run()
                        );
                    });
}

5.发送响应

$response->send();
public function send()
{
    $this->sendHeaders();
    $this->sendContent();

    if (\function_exists('fastcgi_finish_request')) {
        fastcgi_finish_request();
    } elseif (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) {
        static::closeOutputBuffers(0, true);
    }

    return $this;
}


//设置响应头部信息
public function sendHeaders()
{
    // headers have already been sent by the developer
    if (headers_sent()) {
        return $this;
    }

    // headers
    foreach ($this->headers->allPreserveCaseWithoutCookies() as $name => $values) {
        $replace = 0 === strcasecmp($name, 'Content-Type');
        foreach ($values as $value) {
            header($name.': '.$value, $replace, $this->statusCode);
        }
    }

    // cookies
    foreach ($this->headers->getCookies() as $cookie) {
        header('Set-Cookie: '.$cookie, false, $this->statusCode);
    }

    // status
    header(sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText), true, $this->statusCode);

    return $this;
}



//设置响应主体
public function sendContent()
{
    echo $this->content;

    return $this;
}

6.终止程序

$kernel->terminate($request, $response);
//终止程序

public function terminate($request, $response)
{
    $this->terminateMiddleware($request, $response);

    $this->app->terminate();
}

//终止中间件调用
protected function terminateMiddleware($request, $response)
{
    $middlewares = $this->app->shouldSkipMiddleware() ? [] : array_merge(
        $this->gatherRouteMiddleware($request),
        $this->middleware
    );

    foreach ($middlewares as $middleware) {
        if (! is_string($middleware)) {
            continue;
        }

        [$name] = $this->parseMiddleware($middleware);

        $instance = $this->app->make($name);

        if (method_exists($instance, 'terminate')) {
            $instance->terminate($request, $response);
        }
    }
}

参考:
https://segmentfault.com/a/1190000014598466#
https://learnku.com/docs/the-laravel-way/5.6/Tao-4-1/2933

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值