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';
    }

  

posted @ 2019-01-22 11:28  fengzmh  阅读(1013)  评论(0编辑  收藏  举报