標籤:php eth 資料 div logs eol cti 精簡 路由
剛剛開始學Laravel就會接觸到路由
| 123 |
Route::get(‘/‘, function () { return view(‘welcome‘);}); |
後來筆者一本正經的去讀過Route類的代碼,驚訝的發現並沒有get這個方法,之後瞭解到Laravel用了Facade模式。
Facade本質上是一個“把工作推給別人做的”的類。
Facade存在的價值,可以從服務容器談起。服務容器,可見我的另一篇博文,地址:http://www.cnblogs.com/sweng/p/6430374.html
舉個例子,不知道大家以前寫代碼有沒有過obj->method(arg1,arg2)->func(arg3,arg4);的體驗。學過服務容器的讀者知道,這行代碼就是把服務容器裡的對象取出來,並調用他的方法。這對熟悉服務容器裡註冊過哪些類的開發人員來說,這種代碼還是可以接受的。但是如果像路由定義那樣,也要寫成這樣冗長的形式,實在太不優雅了。所以用Facade模式可以很好的精簡代碼長度。
我們先寫一個DB類
| 123456789101112 |
namespace API;class DB{ public function __construct($args){ } public function Write($str){ echo ‘Write:‘.$str.PHP_EOL; } public function Read($str){ echo ‘Read:‘.$str.PHP_EOL; }} |
資料庫讀寫是整個系統非常常用的操作。但是DB類會註冊在服務容器裡,每次資料庫讀寫都要把DB類的對象從服務容器裡取出,實在很不方便。
我們寫一個Facade類
| 123456789101112131415161718 |
class Facade{ public function __construct(){ // } public static function getInstance($classname,$args){ return new $classname($args); } public static function getFacadeAccessor(){ // } public static function __callstatic($method,$arg){ $instance=static::getInstance(static::getFacadeAccessor(),[1,2,3]); return call_user_func_array(array($instance,$method),$arg); }} |
要理解這個類,我們只要關注最後一個函數,就是__callstatic魔術方法。這個方法就是Facade類型對象在調用他自身沒有定義過的函數時,就會調用__callstatic方法,是一個“候選人”的角色。
我們再定義一個DBFacade類
| 12345 |
class DBFacade extends Facade{ public static function getFacadeAccessor(){ return API\DB::class; }} |
每一個Facade子類都要實現getFacadeAccessor方法,返回只是一個類名字串,用來代入getInstance方法,來建立一個真正“做事情”的類。
此時,Facade已經可以用了,我們調用DBFacade的靜態方法
| 1 |
DBFacade::Write(‘hello‘); |
閱讀代碼,我們發現,其實DBFacade是沒有Write方法的,於是就調用他父類Facade的__callstatic魔術方法,魔術方法我們已經在父類裡面實現了。
以前聽過同行抱怨,PHP文法亂,難記。但實際上像魔術方法把Facade實現的非常簡潔,可見文法設計的精妙。
解讀Laravel,看PHP如何?Facade?