初学laravel的时候,看到service provider这一块,一直纠结如何才能打印出容器内所有的service provider,因为光靠config/app.php文件,很难从alias看出其对应的service provider到底是哪个。后来才发现,其实在程序的任意地方(Application启动后),都可以通过 Container::getInstance()这个静态方法获取当前的Application实例。或者可以使用在全局helps.php中定义的的 app()方法来获取当前Application实例。
Route::get('/test', function () { dd(app()); // dd(Illuminate\Container\Container::getInstance()); });
注意: 在laravel中打印变量尤其是“超大型”变量的时候,千万不要直接使用var_dump()。一来不直观,二来大型变量直接 var_dump可能会导致浏览器卡死(我猜应该是卡死在尝试将var_dump数据解析成dom上面)。=。=# 最好使用larave的全局函数dd()或者dump(),输出又美观,又不会卡死浏览器。
ps: 最好用dd吧,少用dump,今天发现一个bug,如果使用dump的话,会导致cookie操作失效=。=# 发起了一个讨论帖。 @2016.07.03
打印出来的Application如下如所示:
serviceProviders:All of the registered service providers. 所有已注册的service provider。其实等同于loadedProviders,只是数组的格式不一样。
loadedProviders:The names of the loaded service providers. 所有已经加载的service provider。等同于serviceProviders。
deferredServices:The deferred services and their providers. 所有延迟加载的service provider。
[绑定名=>service provider]
resolved:An array of the types that have been resolved. 已经解析(resolve)过的绑定关系会记录在这里。
bindings:The container’s bindings. 容器中所有的绑定关系(并未指向真正的绑定实例,只是指向绑定关系的那段代码),即由Container::bind()与Container::singleton()定义的绑定关系。
[绑定名=>[生成绑定实例的闭包函数, 是否单例绑定]]
instances:The container’s shared instances. 容器中所有单例绑定生成的实例对象。
aliases:The registered type aliases. 绑定关系的别名,实际上是[绑定实例的类名=>绑定名]这样一个数组。 这个aliases通过Container::alias(绑定名, 别名)来定义,容器查找绑定关系的时候,会同时查找bindings[]与aliases[]数组。
[绑定实例的类名=>绑定名]
另外,注意这个aliases与/config/app.php文件中定义的aliases数组不同。/config/app.php文件中aliases数组是用来定义类的别名,底层调用的是php的class_alias函数。展开来说:在容器初始化的时候会创建一个Illuminate\Foundation\Bootstrap\RegisterFacades类实例。该实例通过AliasLoader::getInstance()静态方法来创建一个AliasLoader类的单例,并在构造单例时令其读取/config/app.php中的aliases数组,然后再调用该单例的register()方法,将AliasLoader单例的load()方法通过php的spl_autoload_register函数注册为__autoload函数(php在找不到类实现的时候就会自动调用__autoload函数栈来查找类的实现)。就是在这个单例的load()方法中,通过php的class_alias函数来注册类别名的。而容器中的aliases数组其实只是绑定名与绑定实例类名的对应关系。
resolvingCallbacks: 所有已注册的解析回调。 [绑定名=>解析回调的闭包函数]
extenders: 扩展绑定。 [绑定名 => 扩展绑定的闭包函数]