首页 >后端开发 >php教程 >Facade 的运行机制

Facade 的运行机制

WBOY
WBOY原创
2016-06-20 12:26:352029浏览

门面为应用的服务容器中的绑定类提供了一个“静态”接口。该机制原理由 Facade 类实现,Laravel 自带的门面,以及创建的自定义门面,都会继承自 Illuminate\Support\Facades\Facade 基类。

(用Route来举例)

机制流程图:

facade顶层调用

config/app.php'aliases' => [        'App' => Illuminate\Support\Facades\App::class,        'Artisan' => Illuminate\Support\Facades\Artisan::class,        'Auth' => Illuminate\Support\Facades\Auth::class,        'Blade' => Illuminate\Support\Facades\Blade::class,        'Cache' => Illuminate\Support\Facades\Cache::class,        'Config' => Illuminate\Support\Facades\Config::class,        'Cookie' => Illuminate\Support\Facades\Cookie::class,        'Crypt' => Illuminate\Support\Facades\Crypt::class,        'DB' => Illuminate\Support\Facades\DB::class,        'Eloquent' => Illuminate\Database\Eloquent\Model::class,        'Event' => Illuminate\Support\Facades\Event::class,        'File' => Illuminate\Support\Facades\File::class,        'Gate' => Illuminate\Support\Facades\Gate::class,        'Hash' => Illuminate\Support\Facades\Hash::class,        'Lang' => Illuminate\Support\Facades\Lang::class,        'Log' => Illuminate\Support\Facades\Log::class,        'Mail' => Illuminate\Support\Facades\Mail::class,        'Password' => Illuminate\Support\Facades\Password::class,        'Queue' => Illuminate\Support\Facades\Queue::class,        'Redirect' => Illuminate\Support\Facades\Redirect::class,        'Redis' => Illuminate\Support\Facades\Redis::class,        'Request' => Illuminate\Support\Facades\Request::class,        'Response' => Illuminate\Support\Facades\Response::class,        'Route' => Illuminate\Support\Facades\Route::class,  //例如我们看Route,平时我们调用Route::get这样,其实是调用alias的Route,然后这个Route指向了Illuminate\Support\Facades\Route这个类,至于为什么能实现这种机制,需要继续分析        'Schema' => Illuminate\Support\Facades\Schema::class,        'Session' => Illuminate\Support\Facades\Session::class,        'Storage' => Illuminate\Support\Facades\Storage::class,        'URL' => Illuminate\Support\Facades\URL::class,        'Validator' => Illuminate\Support\Facades\Validator::class,        'View' => Illuminate\Support\Facades\View::class,        'Form' => Collective\Html\FormFacade::class,        'Html' => Collective\Html\HtmlFacade::class,    ],

Route.php

(用phpstome的话,comm+b 就能够通过类名找到类所在的源码)

vendor/laravel/framework/src/Illuminate/Support/Facades/Route.php< ?phpnamespace Illuminate\Support\Facades;/** * @see \Illuminate\Routing\Router */class Route extends Facade{    /**     * Get the registered name of the component.     *     * @return string     */    protected static function getFacadeAccessor()  //只知道Route这个类是继承了Facade,并且有一个静态方法getFacadeAccessor,返回一个router的字符串,这是一个静态方法,    {        return 'router';    }}

当我们使用 Route::get(); 时候其实可以看到这里并没有静态的get方法,那么就会调用Facade的魔术方法__callStatic

再次进入Facade的源码,找到一个 __callStatic的静态魔术方法

__callStatic :在对对象不存在的静态方法进行调用时自动执行;

vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.phppublic static function __callStatic($method, $args)    {        $instance = static::getFacadeRoot();  //魔术方法调用后这里再次调用一个关键的getFacadeRoot方法,这个是静态调用        if (! $instance) {            throw new RuntimeException('A facade root has not been set.');        }        switch (count($args)) {            case 0:                return $instance->$method();            case 1:                return $instance->$method($args[0]);            case 2:                return $instance->$method($args[0], $args[1]);            case 3:                return $instance->$method($args[0], $args[1], $args[2]);            case 4:                return $instance->$method($args[0], $args[1], $args[2], $args[3]);            default:                return call_user_func_array([$instance, $method], $args);        }    }

再次进入getFacadeRoot方法的源码(其实也是当前facade文件)

vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php    /**     * The resolved object instances.     *     * @var array     */    protected static $resolvedInstance; //这个是一个存放实例的,这个是用来解析出实例的  public static function getFacadeRoot()    {        return static::resolveFacadeInstance(static::getFacadeAccessor()); //运行了2个方法,其中getFacadeAccessor作为了resolveFacadeInstance的参数来传递    }    /**     * Get the registered name of the component.     *     * @return string     *     * @throws \RuntimeException     */    protected static function getFacadeAccessor() //返回和抛出报错信息    {        throw new RuntimeException('Facade does not implement getFacadeAccessor method.');    }    /**     * Resolve the facade root instance from the container.     *     * @param  string|object  $name     * @return mixed     */    protected static function resolveFacadeInstance($name) //这个方法需要的是一个$name变量,这个变量就是getFacadeAccessor(),也就是在vendor/laravel/framework/src/Illuminate/Support/Facades/Route.php这里的返回的字符串,因为route.php重写了getFacadeAccessor方法,所以能够获取到    {        if (is_object($name)) {              return $name;        }        if (isset(static::$resolvedInstance[$name])) {            return static::$resolvedInstance[$name];        }        return static::$resolvedInstance[$name] = static::$app[$name]; //这里是用$app来解析container里面的对象,以前说过的IOC,将这个获取到的关键字放到$app[]来解析,然后将这个解析的container对象存放到$resolvedInstance,然后返回    }
声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn