解讀Laravel,看PHP如何實現Facade?


剛剛開始學Laravel就會接觸到路由

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類

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類

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類

class DBFacade extends Facade{
	public static function getFacadeAccessor(){
		return API\DB::class;
	}
}

每一個Facade子類都要實現getFacadeAccessor方法,返回只是一個類名字符串,用來代入getInstance方法,來創建一個真正“做事情”的類。

此時,Facade已經可以用了,我們調用DBFacade的靜態方法

DBFacade::Write('hello');

閱讀代碼,我們發現,其實DBFacade是沒有Write方法的,於是就調用他父類Facade的__callstatic魔術方法,魔術方法我們已經在父類里面實現了。

以前聽過同行抱怨,PHP語法亂,難記。但實際上像魔術方法把Facade實現的非常簡潔,可見語法設計的精妙。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM