启动过程
laravel的public/index.php文件.主要是理解Laravel初始的IOC实现
<?php
define('LARAVEL_START', microtime(true));
/*
加载PSR4命名空间
*/
require __DIR__.'/../vendor/autoload.php';
/*
加载框架引导代码
1.创建Application实例,此类是一个容器,是Laravel的DI(IOC)实现。
2.加载一些基础的共享实例,例如Provider,路径变量,系统核心类的别名等
*/
$app = require_once __DIR__.'/../bootstrap/app.php';
/*
使用框架Kernel处理用户的请求,并返回结果给用户
1.获取到kernel实例
2.解析Request请求
3.加载框架基础的服务,变量,配置
4.dispatchRouter,分发路由,执行相应的请求
5.获取到执行完的结果返回Request请求
*/
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
$response = $kernel->handle(
$request = Illuminate\Http\Request::capture()
);
$response->send();
//执行结束,终止脚本
$kernel->terminate($request, $response);
Facade
先分析下Facade的注册过程,也就是框架启动时,如何把config文件中注册的facade注册到系统中
$app = require_once __DIR__.'/../bootstrap/app.php';
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
/*
index.php中,ioc容器建立之后执行Kernel的handle方法
*/
$response = $kernel->handle(
$request = Illuminate\Http\Request::capture()
);
$response->send();
$kernel->terminate($request, $response);
public function handle($request)
{
try {
$request->enableHttpMethodParameterOverride();
//此方法sendRequestThroughRouter中会执行相应的Provider以及Facade
$response = $this->sendRequestThroughRouter($request);
} catch (Throwable $e) {
$this->reportException($e);
$response = $this->renderException($request, $e);
}
$this->app['events']->dispatch(
new RequestHandled($request, $response)
);
return $response;
}
protected function sendRequestThroughRouter($request)
{
$this->app->instance('request', $request);
Facade::clearResolvedInstance('request');
//进行bootstrap方法
$this->bootstrap();
return (new Pipeline($this->app))
->send($request)
->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
->then($this->dispatchToRouter());
}
public function bootstrap()
{
if (! $this->app->hasBeenBootstrapped()) {
//执行bootstrapWith
// 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,
// ];
$this->app->bootstrapWith($this->bootstrappers());
}
}
回到Application类中实现的bootstrapWith方法
public function bootstrapWith(array $bootstrappers)
{
$this->hasBeenBootstrapped = true;
foreach ($bootstrappers as $bootstrapper) {
$this['events']->dispatch('bootstrapping: '.$bootstrapper, [$this]);
//创建实例,并执行实例中的bootstrap方法.
$this->make($bootstrapper)->bootstrap($this);
$this['events']->dispatch('bootstrapped: '.$bootstrapper, [$this]);
}
}
之前bootstrapper中有RegisterFacades类,我们看下RegisterFacades中实现的bootstrap方法
public function bootstrap(Application $app)
{
Facade::clearResolvedInstances();
Facade::setFacadeApplication($app);
//获取app.aliases配置文件中的数据信息,并执行register方法
AliasLoader::getInstance(array_merge(
$app->make('config')->get('app.aliases', []),
$app->make(PackageManifest::class)->aliases()
))->register();
}
//获取到AliasLoader类的实例,执行register去注册spl_autoload_register命名空间
public function register()
{
if (! $this->registered) {
$this->prependToLoaderStack();
$this->registered = true;
}
}
protected function prependToLoaderStack()
{
spl_autoload_register([$this, 'load'], true, true);
}
至此Facade的注册已经完成,接下来我们分析Cache
我们拿Redis的Facade来举例
class Cache extends Facade
{
//复写getFacadeAccessor方法,返回的字符串cache就是注册在ioc中所对应的名字。此方法为必须复写的方法,不复写会报错
protected static function getFacadeAccessor()
{
return 'cache';
}
}
接下来我们看下Facade类,比如当我们执行Cache::set时的流程
//Facade中实现了魔术方法__callStatic,当发现类使用静态调用时,执行此方法
public static function __callStatic($method, $args)
{
//获取对应的facade实例
$instance = static::getFacadeRoot();
if (! $instance) {
throw new RuntimeException('A facade root has not been set.');
}
//使用实例所对应的方法
return $instance->$method(...$args);
}
//分析getFacadeRoot方法
public static function getFacadeRoot()
{ //getFacadeAccessor前面子类已经复写了
return static::resolveFacadeInstance(static::getFacadeAccessor());
}
protected static function resolveFacadeInstance($name)
{
if (is_object($name)) {
return $name;
}
if (isset(static::$resolvedInstance[$name])) {
return static::$resolvedInstance[$name];
}
if (static::$app) {
//因为Application实现了ArrayAccess接口,所以可以直接$app['']
数组方式进行获取实例
return static::$resolvedInstance[$name] = static::$app[$name];
}
}
//ArrayAccess接口的实现,其实也是去make获取实例
public function offsetGet($key)
{
return $this->make($key);
}
Route
看路由解析过程
进入Kernel文件对handle方法的实现
public function handle($request)
{
try {
$request->enableHttpMethodParameterOverride();
$response = $this->sendRequestThroughRouter($request);
} catch (Throwable $e) {
$this->reportException($e);
$response = $this->renderException($request, $e);
}
$this->app['events']->dispatch(
new RequestHandled($request, $response)
);
return $response;
}
protected function sendRequestThroughRouter($request)
{
$this->app->instance('request', $request);
Facade::clearResolvedInstance('request');
$this->bootstrap();
return (new Pipeline($this->app))
->send($request)
->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
->then($this->dispatchToRouter());
}
protected function dispatchToRouter()
{
return function ($request) {
$this->app->instance('request', $request);
return $this->router->dispatch($request);
};
}
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 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()
);
});
}
网友评论