我的博客原文:http://www.qinblog.net/Articl...前言Laravel提供了一个灵活的模型,那就是facade。框架内部的DB、Auth、File等功能也有相关的门面实现。那么,如何编写自己的门面呢?什么是门面?首先,Facade并不是laravel特有的东西,它是设计模式中的外观模式(Facade)。当然这里不长篇大论讨论外观模式的定义。这篇文章写的很好:DesignPatterns(9)AppearancePatternFacade(StructureType)。那么,laravel的门面是做什么的呢?同样,laravel实现了外观模式的切换功能,使用魔术方法__callstatic来实现静态调用和动态创建对象的功能。参考资料(官方文档)当然,你可能觉得这些概念很抽象,什么都不是。所以其实简单来说,laravel的门面就是将某些功能封装到工具类中,可以静态的方式调用工具类的方法。搭建自己的门面首先以laravel5.1框架和我之前写的Geoip门面为例,说说如何搭建自己的门面。下载geoip扩展geoip是一个基于maxmind数据库,通过IP获取国家、地区、城市信息的PHP扩展。github在这里。首先,为laravel添加geoip扩展。打开composer.json,添加"geoip2/geoip2":"~2.0"到要求。在项目根目录下运行composerupdate(需要安装composer)进行更新,geoip的依赖和软件包会被下载到vendor文件夹中。然后下载geoip依赖的数据库,免费库地址:GeoLite2我下载了GeoLite2Country和GeoLite2City库,放在storage/geoipdb。建立门面。在app目录下新建Facades文件夹,新建Facades/GeoIP/GeoIP.php和Facades/GeoIP/Facade/GeoIP.php(建议每个功能都新建一个文件夹,比如我这里新建anewfolderforGeoIP,aboutAllGeoIPthingsareputhere)注意Facades/GeoIP下的GeoIP.php是你要封装geoip扩展的类,Facades/GeoIP/Facade下的GeoIP.php是你的门面,也就是用于laravel解析,两个文件可以有不同的名称。目录结构如图:Facades/GeoIP/Facade/GeoIP.php如下){返回'geoip';注意,你的门面现在只有一个方法,它返回一个字符串'geoip',这是一个标签,供laravel的服务提供者解析。Facades/GeoIP/GeoIP.php如下(吐槽:写的有一点随意)_country_db;}休息;case'getCity':$path=$this->_city_db;休息;默认值:中断;}$this->_instance=newReader(storage_path($path));}/***获取国家信息。**@paramString$ip*@return数组*/publicfunctiongetCountry($ip){$this->init(__FUNCTION__);$record=$this->_instance->country($ip);//国家信息$data['iso_code']=$record->country->isoCode;$data['country_name']=$record->country->name;$data['country_name_zh_cn']=$record->country->names['zh-CN'];返回$数据;}/***获取城市信息。**@paramString$ip*@returnArray*/publicfunctiongetCity($ip){$this->init(__FUNCTION__);$record=$this->_instance->city($ip);$data['iso_code']=$record->country->isoCode;$data['country_name']=$record->country->name;$data['country_name_zh_cn']=$record->country->names['zh-CN'];//省、州信息$data['sub_division_name']=$record->mostSpecificSubdivision->name;$data['sub_division_name_zh_cn']=$record->mostSpecificSubdivision->names['zh-CN'];$data['sub_division_code']=$record->mostSpecificSubdivision->isoCode;//城市信息$data['city_name']=$record->city->name;$data['postal_code']=$record->postal->code;//纬度和经度$data['latitude']=$record->location->latitude;$data['longitude']=$record->location->longitude;返回$数据;}}OK,至此geoip常用的功能已经封装到方法中了。注册服务已经完成了门面的创建和功能封装,接下来就要用到了。自己创建的facade需要注册才能在laravel中使用,这样laraval在启动的时候就可以自动注入依赖(参见laravel的依赖注入介绍:laravel依赖注入学院君)编写服务提供者,在app/Providers下新建一个FacadesServiceProvider.PHP可以手动构建,也可以根据需要使用artisan命令生成。app/Providers/FacadesServiceProvider.php代码如下:app->singleton('geoip',function($app){returnnewGeoIP($app);});}}上面的代码表明,服务提供者注册的时候,会注册一个标签为'geoip'的单例,也就是我们自己的facade返回的单例,然后回调函数会返回一个对象,就是实例封装geoip函数的类。不懂的同学可以看看laravel的服务提供者和服务容器相关知识。(注意use指的是门面的命名空间和封装类。)如果注册的服务提供者是laravel5.1或更高版本,在config/app.php中找到提供者和别名,并配置你的服务提供者和门面别名:providersAdd:App\Providers\FacadeServiceProvider::class,aliasesAdd(不用每次都写很长的命名空间前缀):'GeoIP'=>App\Facades\GeoIP\Facade\GeoIP::class,forlumen5.2andabove,你需要在bootstrap/app.php中添加$app->register(App\Providers\FacadesServiceProvider::class);注册后,每次使用facade::function,laravel都会自动解析facade,然后创建一个对象供用户使用,而不需要用户自己创建一个新的对象。使用现在,在任何控制器或路由回调函数中,使用$res=GeoIP::getCountry('75.101.195.215');var_dump($res);你会发现立面??已经可以很好地工作了,享受吧!参考文章【1】设计模式(九)外观模式门面(结构型)【2】Laravel服务容器实例教程-深入理解控制反转(IoC)和依赖注入(DI)【3】Laravel服务提供者实例教程——--创建一个ServiceProvider测试实例
