laravel学习笔记(十)Facade调用流程
1、public\index.php中调用了bootstrap\app.php:
$app = require_once __DIR__.'/../bootstrap/app.php';
2、bootstrap\app.php中调用了vendor\laravel\framework\src\Illuminate\Foundation\Application.php:
$app = new Illuminate\Foundation\Application( realpath(__DIR__.'/../') );
然后再vendor\laravel\framework\src\Illuminate\Foundation\Application.php构造函数中调用了registerCoreContainerAliases方法设置了别名,如'db' => [\Illuminate\Database\DatabaseManager::class]:
public function __construct($basePath = null) { if ($basePath) { $this->setBasePath($basePath); } $this->registerBaseBindings(); $this->registerBaseServiceProviders(); $this->registerCoreContainerAliases(); }
3、bootstrap\app.php中调用了singleton函数将类App\Http\Kernel绑定到Illuminate\Contracts\Http\Kernel中:
$app->singleton( Illuminate\Contracts\Http\Kernel::class, App\Http\Kernel::class );
4、public\index.php中调用了make方法生成类App\Http\Kernel的实例:
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
5、public\index.php中调用了类App\Http\Kernel实例的父类Illuminate\Foundation\Http\Kernel的handle方法:
$response = $kernel->handle( $request = Illuminate\Http\Request::capture() );
在handle方法中调用了sendRequestThroughRouter方法:
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; }
在sendRequestThroughRouter方法中调用了bootstrap方法:
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()); }
在bootstrap方法中调用了容器vendor\laravel\framework\src\Illuminate\Foundation\Application.php中的bootstrapWith方法执行了$bootstrappers中所有类的bootstrap方法,其中包含\Illuminate\Foundation\Bootstrap\RegisterFacades类:
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, ]; public function bootstrap() { if (! $this->app->hasBeenBootstrapped()) { $this->app->bootstrapWith($this->bootstrappers()); } } protected function bootstrappers() { return $this->bootstrappers; }
public function bootstrapWith(array $bootstrappers) { $this->hasBeenBootstrapped = true; foreach ($bootstrappers as $bootstrapper) { $this['events']->fire('bootstrapping: '.$bootstrapper, [$this]); $this->make($bootstrapper)->bootstrap($this); $this['events']->fire('bootstrapped: '.$bootstrapper, [$this]); } }
6、vendor\laravel\framework\src\Illuminate\Foundation\Bootstrap\RegisterFacades.php中的bootstrap方法中setFacadeApplication方法设置容器信息:
public function bootstrap(Application $app) { Facade::clearResolvedInstances(); Facade::setFacadeApplication($app); AliasLoader::getInstance($app->make('config')->get('app.aliases', []))->register(); }
7、在控制器中调用DB对应的方法时:
use Illuminate\Support\Facades\DB; $data = DB::connection('数据库连接名')->select('sql语句');
由于没有相应的静态函数,首先会调用DB的父类Illuminate\Support\Facades\Facade中的__callStatic方法:
public static function __callStatic($method, $args) { $instance = static::getFacadeRoot(); if (! $instance) { throw new RuntimeException('A facade root has not been set.'); } return $instance->$method(...$args); }
在__callStatic方法中通过static::getFacadeRoot()方法实例化Illuminate\Support\Facades\DB::getFacadeAccessor()别名对应的类,然后通过$instance->$method(...$args)调用实例中对应的方法:
protected static function getFacadeAccessor() { return 'db'; }