Heim > Artikel > Backend-Entwicklung > Facade 的运行机制
门面为应用的服务容器中的绑定类提供了一个“静态”接口。该机制原理由 Facade 类实现,Laravel 自带的门面,以及创建的自定义门面,都会继承自 Illuminate\Support\Facades\Facade 基类。
(用Route来举例)
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, ],
(用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
__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); } }
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,然后返回 }