美文网首页
Laravel 文档 - 请求周期

Laravel 文档 - 请求周期

作者: moralok | 来源:发表于2018-10-25 19:21 被阅读0次

前辈们在社区的学习建议中指出,新手并不适合直接从文档开始。现在的学习是建立在实践了两个教程的项目上的。

生命周期概述

第一件事

  1. Laravel 应用的所有请求入口都是 public/index.php 文件。所有的请求都是经由你的 Web 服务器(Apache/Nginx)通过配置引导到这个文件

  2. index.php 文件加载 Composer 生成的自动加载设置,然后从 bootstrap/app.php 脚本中检索 Laravel 应用程序的实例。 Laravel 本身采取的第一个动作是创建一个 / 服务容器


public/index.php

/*
|--------------------------------------------------------------------------
| 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.
|
*/

require __DIR__.'/../vendor/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.
|
*/

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

bootstrap/app.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 = 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.
|
*/

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

Laravel源码里面为什么要用::class语法?
使用 ClassName::class 你可以获取一个字符串,包含了类 ClassName 的完全限定名称。这对使用了 命名空间 的类尤其有用。

HTTP / Console 内核

  1. 根据进入应用程序的请求类型来将传入的请求发送到 HTTP 内核或控制台内核。这两个内核是用来作为所有请求都要通过的中心位置。

  2. HTTP 内核继承了 Illuminate\Foundation\Http\Kernel 类,该类定义了一个 bootstrappers 数组。


Illuminate\Foundation\Http\Kernel.php

/**
 * The bootstrap classes for the application.
 *
 * @var array
 */
protected $bootstrappers = [
    \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,
    \Illuminate\Foundation\Bootstrap\LoadConfiguration::class,
    \Illuminate\Foundation\Bootstrap\HandleExceptions::class,
    \Illuminate\Foundation\Bootstrap\RegisterFacades::class,
    \Illuminate\Foundation\Bootstrap\RegisterProviders::class,
    \Illuminate\Foundation\Bootstrap\BootProviders::class,
];
  1. 这个数组中的类在请求被执行前运行,这些 bootstrappers 配置了错误处理, 日志, 检测应用环境,以及其它在请求被处理前需要执行的任务。

  2. HTTP 内核还定义了所有请求被应用程序处理之前必须经过的 HTTP 中间件 ,这些中间件处理 HTTP 会话 读写、判断应用是否处于维护模式、 验证 CSRF 令牌 等等。


app/Http/Kernel.php

/**
 * The application's global HTTP middleware stack.
 *
 * These middleware are run during every request to your application.
 *
 * @var array
 */
protected $middleware = [
    \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
    \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
    \App\Http\Middleware\TrimStrings::class,
    \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
    \App\Http\Middleware\TrustProxies::class,
];

/**
 * The application's route middleware groups.
 *
 * @var array
 */
protected $middlewareGroups = [
    'web' => [
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\Session\Middleware\StartSession::class,
        // \Illuminate\Session\Middleware\AuthenticateSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\VerifyCsrfToken::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
    ],

    'api' => [
        'throttle:60,1',
        'bindings',
    ],
];

/**
 * The application's route middleware.
 *
 * These middleware may be assigned to groups or used individually.
 *
 * @var array
 */
protected $routeMiddleware = [
    'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
    'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
    'can' => \Illuminate\Auth\Middleware\Authorize::class,
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
];
  1. HTTP 内核的 handle 方法签名相当简单:获取一个 Request ,返回一个 Response。可以把该内核想象作一个代表整个应用的大黑盒子,输入 HTTP 请求,返回 HTTP 响应。

Illuminate\Foundation\Http\Kernel.php

/**
 * 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. 内核启动操作中最重要的便是你应用的 服务提供者 了。所有应用下的服务提供者均配置在 config/app.php 配置文件中的 providers 数组中。

config/app.php

/*
|--------------------------------------------------------------------------
| Autoloaded Service Providers
|--------------------------------------------------------------------------
|
| The service providers listed here will be automatically loaded on the
| request to your application. Feel free to add your own services to
| this array to grant expanded functionality to your applications.
|
*/

'providers' => [

    /*
     * Laravel Framework Service Providers...
     */
    Illuminate\Auth\AuthServiceProvider::class,
    Illuminate\Broadcasting\BroadcastServiceProvider::class,
    Illuminate\Bus\BusServiceProvider::class,
    Illuminate\Cache\CacheServiceProvider::class,
    Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class,
    Illuminate\Cookie\CookieServiceProvider::class,
    Illuminate\Database\DatabaseServiceProvider::class,
    Illuminate\Encryption\EncryptionServiceProvider::class,
    Illuminate\Filesystem\FilesystemServiceProvider::class,
    Illuminate\Foundation\Providers\FoundationServiceProvider::class,
    Illuminate\Hashing\HashServiceProvider::class,
    Illuminate\Mail\MailServiceProvider::class,
    Illuminate\Notifications\NotificationServiceProvider::class,
    Illuminate\Pagination\PaginationServiceProvider::class,
    Illuminate\Pipeline\PipelineServiceProvider::class,
    Illuminate\Queue\QueueServiceProvider::class,
    Illuminate\Redis\RedisServiceProvider::class,
    Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,
    Illuminate\Session\SessionServiceProvider::class,
    Illuminate\Translation\TranslationServiceProvider::class,
    Illuminate\Validation\ValidationServiceProvider::class,
    Illuminate\View\ViewServiceProvider::class,

    /*
     * Package Service Providers...
     */

    /*
     * Application Service Providers...
     */
    App\Providers\AppServiceProvider::class,
    App\Providers\AuthServiceProvider::class,
    // App\Providers\BroadcastServiceProvider::class,
    App\Providers\EventServiceProvider::class,
    App\Providers\RouteServiceProvider::class,

],
  1. 第一步,所有服务提供者的 register 方法会被调用,然后一旦所有服务提供者均注册后, boot 方法才被调用。

  2. 服务提供者给框架开启多种多样的组件,像数据库,队列,验证器,以及路由组件。只要被启动,服务提供者就可支配框架的所有功能,所以服务提供者也是 Laravel 整个引导周期最重要组成部分。

请求调度

  1. 一旦启动且所有服务提供者被注册,Request 会被递送给路由。
  2. 路由将会调度请求,交给绑定的路由或控制器,当然也包括路由绑定的中间件。

聚焦服务提供者

  1. 服务提供者是 Laravel 生命周期中的真正关键。应用实例一旦创建,服务提供者就被注册,然后请求就会被启动的应用接管。

  2. 牢牢掌握服务提供者的构建和其对 Laravel 应用处理机制的原理是非常有价值的。应用的默认服务提供者会存放在 app/Providers 下面。

  3. 默认的, AppServiceProvider 是空白的。这个提供者是一个不错的位置,用于你添加应用自身的引导处理和服务容器绑定。大型项目中,你可能希望创建数个粒度更精细的服务提供者。

关键词
请求入口index.php、服务容器app、HTTP / Console 内核、引导程序bootstrappers、HTTP中间件middleware、服务提供者:ServiceProvider

额外阅读
Illuminate\Foundation\Application.php
文档似乎没对该文件有所说明

总结
看完后对实现细节感觉还是一脸懵逼

相关文章

网友评论

      本文标题:Laravel 文档 - 请求周期

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