以下由Laravel教學專欄跟大家介紹如何利用PHP trait實作簡易Facade,希望對大家有幫助!
## 簡述
##Facade##簡稱
##Facade
##Laravel
大部分的擴充包都使用了 Facade
。 【推薦:
】下面的簡易Facade 主要利用PHP 的特性trait
,魔術方法__callStatic
,反射類別ReflectionClass
。使用場景
後台系統大部分都會有類似這樣的操作:<?php $user = User::find($id);if (!$user) { throw new \Expection("资源不存在");}
$article = Article::find($id);if (!$article) { throw new \Expection("资源不存在");}$article->delete();
上程式碼
#1、首先我們應該要有一個Service#
<?phpnamespace App\Services;use App\Traits\ModeServiceTrait;class ModelService extends BaseService{ use ModeServiceTrait;}
2、新建一個Trait
trait 為了多繼承而存在的,可以去PHP官網看文件。 <?php namespace App\Traits; use \ReflectionClass; use \Exception;use \ReflectionException; use Illuminate\Database\Eloquent\Model; use App\Exceptions\ResourceException; /** * @method static Model find(string $className, int $id, callable $callback = null) * * @see Model * @package App\Services */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 App\Console\Commands; use Illuminate\Console\Command; use App\Services\ModelService; use App\Models\Article\Article; 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### 一樣的效果。同時也做到了程式碼復用。 ###這樣使用程式會多走很多步,但跟優雅比起來,性能什麼的都無所謂了。 ######表達不是很清楚,需要自己深入體會了。 ### ###以上是用PHP特性trait實現簡易Laravel Facade的詳細內容。更多資訊請關注PHP中文網其他相關文章!