当前位置: 首页 > 后端技术 > PHP

LaravelFacade的加载过程和原理

时间:2023-03-29 16:11:34 PHP

介绍Facades(发音:/f??s?d/)为应用程序的服务容器中可用的类提供一个“静态”接口。您不必使用一堆名称空间,也不必实例化对象来访问对象上的特定方法。使用Config;classTest{publicfunctionindex(){returnConfig::get('app.name');Facade启动和注册Facade启动bootstrap注册在Illuminate\Foundation\Bootstrap\RegisterFacades中。publicfunctionbootstrap(Application$app){Facade::clearResolvedInstances();Facade::setFacadeApplication($app);AliasLoader::getInstance(array_merge($app->make('config')->get('app.aliases',[]),$app->make(PackageManifest::class)->aliases()))->register();}默认别名配置是从app配置文件下的aliases中读取的,PackageManifest是laravel5.5新加入的包自动发现规则,这里我们暂时不考虑PackageManifest包提供的别名。其中array_merge返回以下格式的数组:"App"=>"Illuminate\Support\Facades\App""Artisan"=>"Illuminate\Support\Facades\Artisan""Auth"=>"Illuminate\Support\Facades\Auth""Blade"=>"Illuminate\Support\Facades\Blade"...上面的代码将注册所有外观以通过AliasLoader自动加载。它的核心是php的spl_autoload_register。/***将加载方法添加到自动加载程序堆栈中。**@returnvoid*/protectedfunctionregister(){if(!$this->registered){spl_autoload_register([$this,'load'],true,true);}$this->registered=true;}}注册完成后,所有后续使用的类都会通过load函数自动加载。注意这里定义spl_autoload_register时,最后一个参数传true。当此参数为真时,spl_autoload_register()会将函数添加到队列的头部而不是尾部。(此函数优先于完成自动加载)即aliases[$alias])){returnclass_alias($this->aliases[$alias],$alias);}}关于class_alias这里是官方的帖子例子:classfoo{}class_alias('foo','bar');$a=newfoo;$b=newbar;//对象是一样的var_dump($a==$b,$a===$b);//truevar_dump($ainstanceof$b);//false//类是相同的var_dump($ainstanceoffoo);//truevar_dump($ainstanceofbar);//truevar_dump($binstanceoffoo);//truevar_dump($binstanceofbar);//trueFacade加载当我们使用Facade时,如:$method(...$args);}getFacadeRoot方法用于获取别名类的具体实例,我们知道所有的Facade类都需要定义一个getFacadeAccessor方法。该方法可能的返回值有:String类型字符串(如config、db)String类型类字符串(如App\Service\SomeService)Object具体实例化对象Closure闭包如ConfigFacade的getFacadeAccessor方法如下:protectedstaticfunctiongetFacadeAccessor(){return'config';}getFacadeRoot方法会根据getFacadeAccessor()的返回值从容器中取出对应的真实列对象。公共静态函数getFacadeRoot(){$name=static::getFacadeAccessor();如果(is_object($name)){返回$name;}if(isset(static::$resolvedInstance[$name])){returnstatic::$resolvedInstance[$name];}returnstatic::$resolvedInstance[$name]=static::$app[$name];}因为config真正的列已经注册到APP容器中instance('config',$config=newRepository($items));所以\Config::get('app.name','dafault)实际上访问的是Repository实例的get('app.name','default')方法。