下面给大家介绍如何利用PHP trait实现简易Facade,希望对大家有所帮助!
简述
Facade可以有效帮我实现方法的静态化。Laravel大部分的扩展包都使用了Facade。
下面的简易Facade主要是利用 PHP 的特性trait,魔术方法__callStatic,反射类ReflectionClass。
使用场景
后台系统大部分都会有类似这样的操作:
<?php$user=User::find($id);if(!$user){thrownew\\Expection("资源不存在");}
这样似乎没有什么问题,但是还会存在下面这样的:
$article=Article::find($id);if(!$article){thrownew\\Expection("资源不存在");}$article->delete();
这样写法十分不优雅。
上代码
1、首先我们应该要有一个 Service
<?phpnamespaceApp\\Services;useApp\\Traits\\ModeServiceTrait;classModelServiceextendsBaseService{useModeServiceTrait;}
2、新建一个 Trait
trait 为了多继承而存在的,可以去 PHP官网 看文档。
<?phpnamespaceApp\\Traits;use\\ReflectionClass;use\\Exception;use\\ReflectionException;useIlluminate\\Database\\Eloquent\\Model;useApp\\Exceptions\\ResourceException;/***@methodstaticModelfind(string$className,int$id,callable$callback=null)**@seeModel*@packageApp\\Services*/traitModeServiceTrait{/***回调方法**@paramModel|null$model*@paramstring$method*@returnModel*@throwsResourceException*/publicstaticfunctioncallback(Model|null$model,string$method):Model{switch($method){case'first':case'find':if(!$model){thrownewResourceException("资源不存在");}break;default:break;}return$model;}/***调用不存在的方法时触发**@param$method*@param$args*@returnfalse|mixed*@throwsReflectionException*@throwsResourceException*@throwsException*/publicstaticfunction__callStatic($method,$args){$className=$args[0];$arg=$args[1];//判断模型类是否存在if(!class_exists($className)){thrownewException("Theclass{$className}couldnotbefound.from:".__CLASS__);}//利用反射实例化其类$reflection=newReflectionClass($className);$instance=$reflection->newInstanceArgs();//调用该不存在的方法$model=call_user_func_array([$instance,$method],[$arg]);//如果存在复杂操作交给callbackreturnisset($args[2])?$args[2]($model):self::callback($model,$method);}}
首先我们关注__callStatic这个魔术方法。 当调用不存在的静态方法时会触发该方法。和他相似的魔术方法是__call。这是使用__callStatic是为了达到Facade的效果。
__callStatic有两个回调参数$method是被调用的且不存在的方法,$args是$method方法中所传递的参数(数组形式)。
这样一个简易的trait就完成了。
使用
我们新建一个command
$phpartisanmake:commandTestCommand
写入下面的内容
<?phpnamespaceApp\\Console\\Commands;useIlluminate\\Console\\Command;useApp\\Services\\ModelService;useApp\\Models\\Article\\Article;classTestCommandextendsCommand{/***Thenameandsignatureoftheconsolecommand.**@varstring*/protected$signature='test:test';/***Theconsolecommanddescription.**@varstring*/protected$description='atest';/***Createanewcommandinstance.**@returnvoid*/publicfunction__construct(){parent::__construct();}/***Executetheconsolecommand.*/publicfunctionhandle(){$article=ModelService::find(Article::class,1);$article=ModelService::find(Article::class,1,function($model){return$model->load('author');});}}
其中的Article模型需要自己去创建。
接下来就可以看看效果了:
$phpartisantest:test
结语
这样我们就抛弃了使用abstract抽象类,来达到了跟Facade一样的效果。同时也做到了代码复用。这样使用程序会多走很多步,但是跟优雅比起来,性能什么的都无所谓了。
表达不是很清楚,需要自己深入体会了。
产品猿社区致力收录更多优质的商业产品,给服务商以及软件采购客户提供更多优质的软件产品,帮助开发者变现来实现多方共赢;
日常运营的过程中我们难免会遇到各种版权纠纷等问题,如果您在社区内发现有您的产品未经您授权而被用户提供下载或使用,您可按照我们投诉流程处理,点我投诉;
本文来自用户发布投稿,不代表产品猿立场 ;若对此文有疑问或内容有严重错误,可联系平台客服反馈;
部分产品是用户投稿,可能本文没有提供官方下下载地址或教程,若您看到的内容没有下载入口,您可以在我们产品园商城搜索看开发者是否有发布商品;若您是开发者,也诚邀您入驻商城平台发布的产品,地址:点我进入;
如若转载,请注明出处:https://www.chanpinyuan.cn/36640.html;