解读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实现的很是简洁,可见语法设计的精妙。

相关文章
相关标签/搜索