Laravel源碼解析一 【請求的生命週期】

不BB,直接開始。
看一個框架的源碼,第一步咱們先看入口文件。
laravel的入口文件在public目錄下的index.phpphp

require __DIR__.'/../bootstrap/autoload.php';

這玩意是加載composer的一些東西,自動加載有須要的類。具體的也很少說,主要是我還沒玩會這玩意。
接着看laravel

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

這裏要看bootstrap目錄下的app.php文件
這個文件裏映入眼簾的就是web

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

好吧。new一個application出來。那麼咱們找到Illuminate\Foundation\Application這個文件redis

public function __construct($basePath = null)
    {
        $this->registerBaseBindings();

        $this->registerBaseServiceProviders();

        $this->registerCoreContainerAliases();

        if ($basePath) {
            $this->setBasePath($basePath);
        }
    }

new application時的構造函數長這個樣子。寫到這的時候,我忽然以爲加個序號可能會比較好。bootstrap

(一) new Application的過程

1.1先是註冊基本綁定,也就是 $this->registerBaseBindings();這個方法裏的內容數組

protected function registerBaseBindings() {
        static::setInstance($this);

        $this->instance('app', $this);

        $this->instance('Illuminate\Container\Container', $this);

    }

巨簡單的過程,就是把實例化的的application 賦值給app和Illuminate\Container\Container瀏覽器

1.2註冊基本的服務提供者。$this->registerBaseServiceProviders();ruby

protected function registerBaseServiceProviders() {
        $this->register(new EventServiceProvider($this));

        $this->register(new RoutingServiceProvider($this));
    }

這裏經過名字能夠感受出是註冊了事件服務提供者和路由服務提供者cookie

1.3註冊核心類名的別名$this->registerCoreContainerAliases();session

public function registerCoreContainerAliases()
    {
        $aliases = [ 'app' => ['Illuminate\Foundation\Application', 'Illuminate\Contracts\Container\Container', 'Illuminate\Contracts\Foundation\Application'], 'auth' => ['Illuminate\Auth\AuthManager', 'Illuminate\Contracts\Auth\Factory'], 'auth.driver' => ['Illuminate\Contracts\Auth\Guard'], 'blade.compiler' => ['Illuminate\View\Compilers\BladeCompiler'], 'cache' => ['Illuminate\Cache\CacheManager', 'Illuminate\Contracts\Cache\Factory'], 'cache.store' => ['Illuminate\Cache\Repository', 'Illuminate\Contracts\Cache\Repository'], 'config' => ['Illuminate\Config\Repository', 'Illuminate\Contracts\Config\Repository'], 'cookie' => ['Illuminate\Cookie\CookieJar', 'Illuminate\Contracts\Cookie\Factory', 'Illuminate\Contracts\Cookie\QueueingFactory'], 'encrypter' => ['Illuminate\Encryption\Encrypter', 'Illuminate\Contracts\Encryption\Encrypter'], 'db' => ['Illuminate\Database\DatabaseManager'], 'db.connection' => ['Illuminate\Database\Connection', 'Illuminate\Database\ConnectionInterface'], 'events' => ['Illuminate\Events\Dispatcher', 'Illuminate\Contracts\Events\Dispatcher'], 'files' => ['Illuminate\Filesystem\Filesystem'], 'filesystem' => ['Illuminate\Filesystem\FilesystemManager', 'Illuminate\Contracts\Filesystem\Factory'], 'filesystem.disk' => ['Illuminate\Contracts\Filesystem\Filesystem'], 'filesystem.cloud' => ['Illuminate\Contracts\Filesystem\Cloud'], 'hash' => ['Illuminate\Contracts\Hashing\Hasher'], 'translator' => ['Illuminate\Translation\Translator', 'Symfony\Component\Translation\TranslatorInterface'], 'log' => ['Illuminate\Log\Writer', 'Illuminate\Contracts\Logging\Log', 'Psr\Log\LoggerInterface'], 'mailer' => ['Illuminate\Mail\Mailer', 'Illuminate\Contracts\Mail\Mailer', 'Illuminate\Contracts\Mail\MailQueue'], 'auth.password' => ['Illuminate\Auth\Passwords\PasswordBrokerManager', 'Illuminate\Contracts\Auth\PasswordBrokerFactory'], 'auth.password.broker' => ['Illuminate\Auth\Passwords\PasswordBroker', 'Illuminate\Contracts\Auth\PasswordBroker'], 'queue' => ['Illuminate\Queue\QueueManager', 'Illuminate\Contracts\Queue\Factory', 'Illuminate\Contracts\Queue\Monitor'], 'queue.connection' => ['Illuminate\Contracts\Queue\Queue'], 'queue.failer' => ['Illuminate\Queue\Failed\FailedJobProviderInterface'], 'redirect' => ['Illuminate\Routing\Redirector'], 'redis' => ['Illuminate\Redis\Database', 'Illuminate\Contracts\Redis\Database'], 'request' => ['Illuminate\Http\Request', 'Symfony\Component\HttpFoundation\Request'], 'router' => ['Illuminate\Routing\Router', 'Illuminate\Contracts\Routing\Registrar'], 'session' => ['Illuminate\Session\SessionManager'], 'session.store' => ['Illuminate\Session\Store', 'Symfony\Component\HttpFoundation\Session\SessionInterface'], 'url' => ['Illuminate\Routing\UrlGenerator', 'Illuminate\Contracts\Routing\UrlGenerator'], 'validator' => ['Illuminate\Validation\Factory', 'Illuminate\Contracts\Validation\Factory'], 'view' => ['Illuminate\View\Factory', 'Illuminate\Contracts\View\Factory'], ]; foreach ($aliases as $key => $aliases) {
            foreach ($aliases as $alias) {
                $this->alias($key, $alias); } } }

這個方法更簡單,就是一個別名數組,而後經過for循環調用$this->alias()給Application類的父類Container裏的aliases數組裏。

1.4設置基本路徑,咱們在new Application時傳入的 realpath(DIR.’/../’)這個參數賦值給基本路徑

(二)註冊共享的Kernel和異常處理器

咱們的app也new好了,咱們接着app.php裏往下走能夠看到

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

這三個具體幹嗎的咱們之後分析,而後app.php最後返回的是app實例

(三)處理請求和響應

app.php文件執行完之後回到index.php 能夠看到

$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);

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

$response->send();

$kernel->terminate($request, $response);

3.1解析Illuminate\Contracts\Http\Kernel,實例化App\Http\Kernel

3.2實例化後的kernel處理本次請求。這裏$kernel->handle()傳入的參數是一個request。
這裏的request是通過Symfony封裝的請求對象。講道理看到這的時候我有點懵逼。臥槽,我剛開始學laravel,還沒整明白呢,就又多了一個Symfony要學,至少得了解怎麼封裝的請求對象。好煩呀。。。

3.3是將請求處理後的返回結果發送到瀏覽器裏

3.4處理繼承自TerminableMiddleware接口的中間件(Session)並結束應用生命週期。

以上就是laravel框架裏執行一次請求所要經歷的生命週期。 具體的如何註冊如何加載如何封裝請求,我會隨着本身知識的積累和分析源碼來作出解答。 順便,我也是剛開始學習laravel。一塊兒加油!