所需知识点闭包PHP5.3.0引入了闭包和匿名函数。闭包是:创建时封装周围状态的函数。即使闭包所在的环境不再存在,封装在闭包中的状态仍然存在。理论上,闭包和匿名函数是不同的概念。但PHP将其视为相同的概念。事实上,闭包和匿名函数都是伪装成函数的对象。它们是Closure类的实例。闭包是一流的值类型,如字符串和整数。创建一个闭包:registerProviders();}/***添加一个提供者。**@paramstring$provider**@returnApplication*/publicfunctionaddProvider($provider){array_push($this->providers,$provider);返回$这个;}/***设置供应商。**@param数组$providers*/publicfunctionsetProviders(array$providers){$this->providers=[];foreach($providersas$provider){$this->addProvider($provider);}}/***返回所有提供者。**@return数组*/publicfunctiongetProviders(){return$this->providers;}/***魔术获取访问权限。**@paramstring$id**@returnmixed*/publicfunction__get($id){return$this->offsetGet($id);}}/***魔术集访问。**@paramstring$id*@parammixed$value*/publicfunction__set($id,$value){$this->offsetSet($id,$value);}}如何使用我们的应用程序:$app=newApplication([]);$user=$app->user;那么我们可以使用$user对象的方法,我们发现其实并没有$this->user这个属性,但是可以直接使用。主要是这两个方法发挥作用:publicfunctionoffsetSet($id,$value){}publicfunctionoffsetGet($id){}下面我们就来解释下Pimple在执行这两行代码时做了什么。但在解释这个之前,让我们先了解一下容器的一些核心概念。服务提供者服务提供者是连接容器和具体功能实现类的桥梁。服务提供者需要实现接口ServiceProviderInterface:namespacePimple;/***Pimple服务提供者接口。**@authorFabienPotencier*@authorDominikZogg*/interfaceServiceProviderInterface{/***在给定容器上注册服务。**此方法只能用于配置服务和参数。*它不应该得到服务。**@paramContainer$pimple容器实例*/publicfunctionregister(Container$pimple);}所有服务提供者都必须实现接口register方法。我们的应用程序默认有2个服务提供者:protected$providers=[ServiceProviders\ServerServiceProvider::class,ServiceProviders\UserServiceProvider::class];以UserServiceProvider为例,看看它的代码实现:namespaceEasyWeChat\Foundation\ServiceProviders;使用EasyWeChat\User\User;使用Pimple\Container;使用Pimple\ServiceProviderInterface;/***UserServiceProvider类。*/classUserServiceProviderimplementsServiceProviderInterface{/***在给定容器上注册服务。**此方法只能用于配置服务和参数。*它不应该得到服务。**@paramContainer$pimple容器实例*/publicfunctionregister(Container$pimple){$pimple['user']=function($pimple){returnnewUser($pimple['access_token']);};}}我们看到服务提供者的注册方法会在容器中添加属性user,但是返回的不是一个对象,而是一个闭包。我稍后会解释这个。对于服务注册,我们在Application的构造函数中使用$this->registerProviders();注册所有服务提供者:privatefunctionregisterProviders(){foreach($this->providersas$provider){$this->register(new$provider());}}仔细看,发现这里实例化了服务提供者,调用了容器Pimple的注册方法:publicfunctionregister(ServiceProviderInterface$provider,array$values=array()){$provider->register($这个);foreach($valuesas$key=>$value){$this[$key]=$value;}return$this;}而这里又调用了服务提供者的register方法,也就是我们在上一节中提到的:注册方法在容器中添加了属性user,但是返回的不是一个对象,而是关闭。当我们给容器Pimple添加属性user时,会调用offsetSet($id,$value)方法:分别给容器Pimple的属性values和keys赋值:$this->values[$id]=$value;$this->keys[$id]=true;到这里,我们还没有实例化实际提供实际功能的EasyWeChat\User\Usr类。但是,服务提供商的注册已经完成。当我们在这里运行时:$user=$app->user;将调用offsetGet($id)并实例化真正的类:$raw=$this->values[$id];$val=$this->values[$id]=$raw($this);$this->raw[$id]=$raw;$this->frozen[$id]=true;return$val;$raw获取闭包:$pimple['user']=function($pimple){returnnewUser($疙瘩['access_token']);};$raw($this)返回实例化对象User。也就是说只有实际的调用才会实例化具体的类。后面我们可以通过$this['user']或者$this->user来调用User类中的方法。当然,Pimple中还有很多值得我们深入研究的特性,这里就不做过多解释了。参考1.PHP:ArrayAccess-Manualhttp://php.net/manual/zh/clas...2.使用SPL快速实现Observer设计模式https://www.ibm.com/developer...3、Pimple-一个简单的PHP依赖注入容器https://pimple.sensiolabs.org/4、为什么在Laravel源代码中使用::class语法?-知乎https://www.zhihu.com/questio...5、Laravel学习笔记——神奇的服务容器|LaravelChinaCommunity-高质量的Laravel和PHP开发者社区-PoweredbyPHPHubhttps://laravel-china.org/top...6、Pimple/README_zh.rstatmaster52fhy/Pimplehttps://github.com/52fhy/皮条客...原文发表于博客园:http://www.cnblogs.com/52fhy/...欢迎关注公众号,及时获取最新文章!【推荐】PHP进阶之路总结:从亿级PV项目的架构到性能提升的实战,再到更大体系下的服务治理框架的构建和使用。最后,不要拘泥于一种语言,用java快速搭建一套api服务。内容:纯干货!讲师是周孟康,阿里巴巴高级研发工程师,《深入 PHP 内核》的作者之一。有兴趣的朋友可以点击试试看!推荐!您每月只需2.5即可拥有带SSD的VPS!
