Facade 的运行机制

WBOY
Release: 2016-06-20 12:26:35
Original
1991 people have browsed it

门面为应用的服务容器中的绑定类提供了一个“静态”接口。该机制原理由 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,    ],
Copy after login

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';    }}
Copy after login

当我们使用 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);        }    }
Copy after login

再次进入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,然后返回    }
Copy after login
Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template