這篇文章主要介紹了Laravel框架生命週期與原理,結合實例形式總結分析了Laravel框架針對用戶請求響應的完整運行週期、流程、原理,需要的朋友可以參考下
本文實例講述了Laravel框架生命週期與原理。分享給大家供大家參考,具體如下:
#引言:
#如果你對一件工具的使用原理瞭如指掌,那麼你在用這件工具的時候會充滿信心!
正文:
一旦使用者(瀏覽器)發送了一個HTTP請求,我們的apache或nginx一般都會轉到index.php ,因此,之後的一系列步驟都是從index.php開始的,我們先來看看這個檔案程式碼。
<?php require __DIR__.'/../bootstrap/autoload.php'; $app = require_once __DIR__.'/../bootstrap/app.php'; /* |-------------------------------------------------------------------------- | Run The Application |-------------------------------------------------------------------------- | | Once we have the application, we can handle the incoming request | through the kernel, and send the associated response back to | the client's browser allowing them to enjoy the creative | and wonderful application we have prepared for them. | */ $kernel = $app->make(Illuminate\Contracts\Http\Kernel::class); $response = $kernel->handle( $request = Illuminate\Http\Request::capture() ); $response->send(); $kernel->terminate($request, $response);
作者在註解裡談了kernel的作用,kernel的作用,kernel處理來訪的請求,並且發送相應返回給用戶瀏覽器。
這裡又牽涉到了一個app對象,所以附上app對象,所以附上app對象的源碼,這份源碼是\bootstrap\app.php
<?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;
請看app變數是Illuminate\Foundation\Application類別的對象,所以呼叫了這個類別的建構函數,具體做了什麼事,我們看源碼。
public function __construct($basePath = null) { if ($basePath) { $this->setBasePath($basePath); } $this->registerBaseBindings(); $this->registerBaseServiceProviders(); $this->registerCoreContainerAliases(); }
建構器做了3件事,前兩件事很好理解,創建Container,註冊了ServiceProvider,看程式碼
/** * Register the basic bindings into the container. * * @return void */ protected function registerBaseBindings() { static::setInstance($this); $this->instance('app', $this); $this->instance(Container::class, $this); } /** * Register all of the base service providers. * * @return void */ protected function registerBaseServiceProviders() { $this->register(new EventServiceProvider($this)); $this->register(new LogServiceProvider($this)); $this->register(new RoutingServiceProvider($this)); }
最後一件事,是做了一個很大的數組,定義了大量的別名,側面體現程式設計師是聰明的懶人。
/** * Register the core class aliases in the container. * * @return void */ public function registerCoreContainerAliases() { $aliases = [ 'app' => [\Illuminate\Foundation\Application::class, \Illuminate\Contracts\Container\Container::class, \Illuminate\Contracts\Foundation\Application::class], 'auth' => [\Illuminate\Auth\AuthManager::class, \Illuminate\Contracts\Auth\Factory::class], 'auth.driver' => [\Illuminate\Contracts\Auth\Guard::class], 'blade.compiler' => [\Illuminate\View\Compilers\BladeCompiler::class], 'cache' => [\Illuminate\Cache\CacheManager::class, \Illuminate\Contracts\Cache\Factory::class], 'cache.store' => [\Illuminate\Cache\Repository::class, \Illuminate\Contracts\Cache\Repository::class], 'config' => [\Illuminate\Config\Repository::class, \Illuminate\Contracts\Config\Repository::class], 'cookie' => [\Illuminate\Cookie\CookieJar::class, \Illuminate\Contracts\Cookie\Factory::class, \Illuminate\Contracts\Cookie\QueueingFactory::class], 'encrypter' => [\Illuminate\Encryption\Encrypter::class, \Illuminate\Contracts\Encryption\Encrypter::class], 'db' => [\Illuminate\Database\DatabaseManager::class], 'db.connection' => [\Illuminate\Database\Connection::class, \Illuminate\Database\ConnectionInterface::class], 'events' => [\Illuminate\Events\Dispatcher::class, \Illuminate\Contracts\Events\Dispatcher::class], 'files' => [\Illuminate\Filesystem\Filesystem::class], 'filesystem' => [\Illuminate\Filesystem\FilesystemManager::class, \Illuminate\Contracts\Filesystem\Factory::class], 'filesystem.disk' => [\Illuminate\Contracts\Filesystem\Filesystem::class], 'filesystem.cloud' => [\Illuminate\Contracts\Filesystem\Cloud::class], 'hash' => [\Illuminate\Contracts\Hashing\Hasher::class], 'translator' => [\Illuminate\Translation\Translator::class, \Illuminate\Contracts\Translation\Translator::class], 'log' => [\Illuminate\Log\Writer::class, \Illuminate\Contracts\Logging\Log::class, \Psr\Log\LoggerInterface::class], 'mailer' => [\Illuminate\Mail\Mailer::class, \Illuminate\Contracts\Mail\Mailer::class, \Illuminate\Contracts\Mail\MailQueue::class], 'auth.password' => [\Illuminate\Auth\Passwords\PasswordBrokerManager::class, \Illuminate\Contracts\Auth\PasswordBrokerFactory::class], 'auth.password.broker' => [\Illuminate\Auth\Passwords\PasswordBroker::class, \Illuminate\Contracts\Auth\PasswordBroker::class], 'queue' => [\Illuminate\Queue\QueueManager::class, \Illuminate\Contracts\Queue\Factory::class, \Illuminate\Contracts\Queue\Monitor::class], 'queue.connection' => [\Illuminate\Contracts\Queue\Queue::class], 'queue.failer' => [\Illuminate\Queue\Failed\FailedJobProviderInterface::class], 'redirect' => [\Illuminate\Routing\Redirector::class], 'redis' => [\Illuminate\Redis\RedisManager::class, \Illuminate\Contracts\Redis\Factory::class], 'request' => [\Illuminate\Http\Request::class, \Symfony\Component\HttpFoundation\Request::class], 'router' => [\Illuminate\Routing\Router::class, \Illuminate\Contracts\Routing\Registrar::class, \Illuminate\Contracts\Routing\BindingRegistrar::class], 'session' => [\Illuminate\Session\SessionManager::class], 'session.store' => [\Illuminate\Session\Store::class, \Illuminate\Contracts\Session\Session::class], 'url' => [\Illuminate\Routing\UrlGenerator::class, \Illuminate\Contracts\Routing\UrlGenerator::class], 'validator' => [\Illuminate\Validation\Factory::class, \Illuminate\Contracts\Validation\Factory::class], 'view' => [\Illuminate\View\Factory::class, \Illuminate\Contracts\View\Factory::class], ]; foreach ($aliases as $key => $aliases) { foreach ($aliases as $alias) { $this->alias($key, $alias); } } }
這裡出現了一個instance函數,其實這並不是Application類別的函數,而是Application類別的父類別Container類別的函數
/** * Register an existing instance as shared in the container. * * @param string $abstract * @param mixed $instance * @return void */ public function instance($abstract, $instance) { $this->removeAbstractAlias($abstract); unset($this->aliases[$abstract]); // We'll check to determine if this type has been bound before, and if it has // we will fire the rebound callbacks registered with the container and it // can be updated with consuming classes that have gotten resolved here. $this->instances[$abstract] = $instance; if ($this->bound($abstract)) { $this->rebound($abstract); } }
Application是Container的子類,所以$app
不僅是Application類別的對象,還是Container的對象,所以,新出現的singleton函數我們就可以到Container類別的原始碼檔案裡查。 bind函數和singleton的差別請見這篇文章。
singleton這個函數,前一個參數是實際類別名,後者參數是類別的「別名」。
$app
物件宣告了3個單例模型對象,分別是HttpKernel,ConsoleKernel,ExceptionHandler。請注意,這裡並沒有創建對象,只是聲明,也只是起了一個「別名」。
大家有沒有發現,index.php中也有一個$kernel變量,但是只保存了make出來的HttpKernel變量,因此本文不再討論,ConsoleKernel,ExceptionHandler。 。 。
繼續在資料夾下找到App\Http\Kernel.php,既然我們把實際的HttpKernel做的事情都寫在這個php檔案裡,就從這份程式碼裡看看究竟做了哪些事?
<?php namespace App\Http; use Illuminate\Foundation\Http\Kernel as HttpKernel; class Kernel extends HttpKernel { /** * 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, //\App\Http\Middleware\MyMiddleware::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\View\Middleware\ShareErrorsFromSession::class, \App\Http\Middleware\VerifyCsrfToken::class, ], 'api' => [ 'throttle:60,1', ], ]; /** * The application's route middleware. * * These middleware may be assigned to groups or used inpidually. * * @var array */ protected $routeMiddleware = [ 'auth' => \App\Http\Middleware\Authenticate::class, 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 'mymiddleware'=>\App\Http\Middleware\MyMiddleware::class, ]; }
一目了然,HttpKernel裡定義了中間件陣列。
該做的做完了,就開始了請求到回應的過程,見index.php
#$response = $kernel->handle( $request = Illuminate\Http\Request::capture() ); $response->send();
最後在中止,釋放所有資源。
/** * Call the terminate method on any terminable middleware. * * @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Response $response * @return void */ public function terminate($request, $response) { $this->terminateMiddleware($request, $response); $this->app->terminate(); }
總結一下,簡單歸納整個過程就是:
1.index.php載入\ bootstrap\app.php,在Application類別的建構子中建立Container,註冊了ServiceProvider,定義了別名數組,然後用app變數保存建構子建構出來的物件。
2.使用app這個對象,建立1個單例模式的物件HttpKernel,在建立HttpKernel時呼叫了建構函數,完成了中間件的宣告。
3.以上這些工作都是在請求來訪之前完成的,接下來開始等待請求,然後就是:接受到請求-->處理請求 -->發送回應-->中止app變數
#以上就是本文的全部內容,希望對大家的學習有所幫助,更相關內容請關注PHP中文網!
相關推薦:
##
以上是對於Laravel框架的生命週期與原理分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!