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

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

Route::get('/', function () {
	return view('welcome');
});

後來筆者一本正經的去讀過Route類的代碼,驚訝的發現並無get這個方法,以後瞭解到Laravel用了Facade模式。html

Facade本質上是一個「把工做推給別人作的」的類。數據庫

Facade存在的價值,能夠從服務容器談起。服務容器,可見個人另外一篇博文,地址:http://www.cnblogs.com/sweng/p/6430374.html函數

舉個例子,不知道你們之前寫代碼有沒有過obj->method(arg1,arg2)->func(arg3,arg4);的體驗。學過服務容器的讀者知道,這行代碼就是把服務容器裏的對象取出來,並調用他的方法。這對熟悉服務容器裏註冊過哪些類的開發人員來講,這種代碼仍是能夠接受的。可是若是像路由定義那樣,也要寫成這樣冗長的形式,實在太不優雅了。因此用Facade模式能夠很好的精簡代碼長度。spa

咱們先寫一個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類的對象從服務容器裏取出,實在很不方便。htm

咱們寫一個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方法,是一個「候選人」的角色。blog

咱們再定義一個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實現的很是簡潔,可見語法設計的精妙。

相關文章
相關標籤/搜索