用PHP特性trait實現簡易Laravel Facade

下面由laravel教程欄目給大家介紹如何利用php trait實現簡易facade,希望對大家有所幫助!

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

簡述

Facade 可以有效幫我實現方法的靜態化。Laravel 大部分的擴展包都使用了 Facade。【推薦:laravel
下面的簡易 Facade 主要是利用 PHP 的特性 trait,魔術方法 __callStatic,反射類 ReflectionClass。

使用場景

后臺系統大部分都會有類似這樣的操作:

立即學習PHP免費學習筆記(深入)”;

<?php $user = User::find($id);if (!$user) {     throw new Expection("資源不存在");}

這樣似乎沒有什么問題,但是還會存在下面這樣的:

$article = Article::find($id);if (!$article) {     throw new Expection("資源不存在");}$article->delete();

這樣寫法十分不優雅。

上代碼

1、首先我們應該要有一個 Service

<?phpnamespace AppServices;use AppTraitsModeServiceTrait;class ModelService extends BaseService{     use ModeServiceTrait;}

2、新建一個 Trait

trait 為了繼承而存在的,可以去 PHP官網 看文檔。

<?php namespace AppTraits; use ReflectionClass; use Exception;use ReflectionException; use IlluminateDatabaseEloquentModel; use AppExceptionsResourceException; /**  * @method static Model find(string $className, int $id, callable $callback = null)  *  * @see Model  * @package AppServices  */trait ModeServiceTrait{     /**      * 回調方法      *      * @param Model|null $model      * @param string $method      * @return Model      * @throws ResourceException      */     public static function callback(Model|null $model, string $method): Model    {         switch ($method)         {             case 'first':             case 'find':                 if (!$model) {                     throw new ResourceException("資源不存在");                 }                 break;              default:                  break;         }          return $model;     }      /**      * 調用不存在的方法時觸發      *      * @param $method      * @param $args      * @return false|mixed      * @throws ReflectionException      * @throws ResourceException      * @throws Exception      */     public static function __callStatic($method, $args)     {         $className = $args[0];         $arg = $args[1];          // 判斷模型類是否存在         if (!class_exists($className)) {             throw new Exception("The class {$className} could not be found. from:" . __CLASS__);         }          // 利用反射實例化其類         $reflection = new ReflectionClass($className);         $instance = $reflection->newInstanceArgs();          // 調用該不存在的方法         $model = call_user_func_array([$instance, $method], [$arg]);          // 如果存在復雜操作交給 callback         return isset($args[2]) ? $args[2]($model) : self::callback($model, $method);     }}

首先我們關注 __callStatic 這個魔術方法。 當調用不存在的靜態方法時會觸發該方法。和他相似的魔術方法是 __call。這是使用 __callStatic 是為了達到 Facade 的效果。

__callStatic 有兩個回調參數 $method 是 被調用的且不存在的方法,$args 是 $method 方法中所傳遞的參數(數組形式)。

這樣一個簡易的 trait 就完成了。

使用

我們新建一個 command

$ php artisan make:command TestCommand

寫入下面的內容

<?php namespace AppConsoleCommands; use IlluminateConsoleCommand; use AppServicesModelService; use AppModelsArticleArticle; class TestCommand extends Command{     /**      * The name and signature of the console command.      *      * @var string      */     protected $signature = 'test:test';      /**      * The console command description.      *      * @var string      */     protected $description = 'a test';      /**      * Create a new command instance.      *      * @return void      */     public function __construct()     {         parent::__construct();     }      /**      * Execute the console command.      */     public function handle()     {         $article = ModelService::find(Article::class, 1);          $article = ModelService::find(Article::class, 1, function ($model) {             return $model->load('author');         });     }}

其中的 Article 模型需要自己去創建。
接下來就可以看看效果了:

$ php artisan test:test

結語

這樣我們就拋棄了使用 abstract 抽象類,來達到了跟 Facade 一樣的效果。同時也做到了代碼復用。
這樣使用程序會多走很多步,但是跟優雅比起來,性能什么的都無所謂了。

表達不是很清楚,需要自己深入體會了。? ? ? ? ? ? ? ? ? ??? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

? 版權聲明
THE END
喜歡就支持一下吧
點贊12 分享