大家好, 今天带来的内容是 Laravel 的 Facade 机制实现原理.
Facade 的简单使用
数据库的使用:
$users = DB::connection('foo')->select(...);
IoC 容器
众所周知, IoC 容器是 Laravel 框架的最最重要的部分. 它提供了两个功能, IoC 和容器.
IoC(Inversion of Control), 也叫控制反转. 说白了, 就是控制对象的生成, 使开发者不用关心对象的如何生成, 只需要关心它的使用即可.
而通过 IoC 机制生成的对象实例需要一个存放的位置, 以便之后继续使用, 便是它的容器功能.
这次不准备讲解 IoC 容器的具体实现, 之后会有文章详细解读它. 关于 IoC 容器, 读者只需要记住两点即可:
根据配置生成对象实例;
保存对象实例, 方便随时取用;
简化后 Facade 类
- <?PHP
- namespace facades;
- abstract class Facade
- {
- protected static $App;
- /**
- * Set the application instance.
- *
- * @param \Illuminate\Contracts\Foundation\Application $App
- * @return void
- */
- public static function setFacadeApplication($App)
- {
- static::$App = $App;
- }
- /**
- * Get the registered name of the component.
- *
- * @return string
- *
- * @throws \RuntimeException
- */
- protected static function getFacadeAccessor()
- {
- throw new RuntimeException('Facade does not implement getFacadeAccessor method.');
- }
- /**
- * Get the root object behind the facade.
- *
- * @return mixed
- */
- public static function getFacadeRoot()
- {
- return static::resolveFacadeInstance(static::getFacadeAccessor());
- }
- /**
- * Resolve the facade root instance from the container.
- *
- * @param string|object $name
- * @return mixed
- */
- protected static function resolveFacadeInstance($name)
- {
- return static::$App->instances[$name];
- }
- public static function __callStatic($method, $args)
- {
- $instance = static::getFacadeRoot();
- if (! $instance) {
- throw new RuntimeException('A facade root has not been set.');
- }
- switch (count($args)) {
- case 0:
- return $instance->$method();
- case 1:
- return $instance->$method($args[0]);
- case 2:
- return $instance->$method($args[0], $args[1]);
- case 3:
- return $instance->$method($args[0], $args[1], $args[2]);
- case 4:
- return $instance->$method($args[0], $args[1], $args[2], $args[3]);
- default:
- return call_user_func_array([$instance, $method], $args);
- }
- }
- }
代码说明:
$App 中存放的就是一个 IoC 容器实例, 它是在框架初始化时, 通过 setFacadeApplication() 这个静态方法设置的
它实现了 __callStatic 魔术方法
getFacadeAccessor() 方法需要子类去继承, 返回一个 string 的标识, 通过这个标识, IoC 容器便能返回它所绑定类 (框架初始化或其它时刻绑定) 的对象
通过 $instance 调用具体的方法
创建自己的 Facade:
TEST1 的具体逻辑:
- <?PHP
- class Test1
- {
- public function hello()
- {
- print("hello world");
- }
- }
TEST1 类的 Facade:
- <?PHP
- namespace facades;
- /**
- * Class Test1
- * @package facades
- *
- * @method static setOverRecommendInfo [设置播放完毕时的回调函数]
- * @method static setHandlerPlayer [明确指定下一首时的执行类]
- */
- class Test1Facade extends Facade
- {
- protected static function getFacadeAccessor()
- {
- return 'test1';
- }
- }
使用:
- use facades\Test1Facade;
- Test1Facade::hello(); // 这是 Facade 调用
解释:
facades\Test1Facade 调用静态方法 hello() 时, 由于没有定义此方法, 会调用 __callStatic;
在 __callStatic 中, 首先是获取对应的实例, 即
return static::$App->instances[$name];
. 这其中的 $name, 即为 facades\Test1 里的 test1
$App, 即为 IoC 容器, 类的实例化过程, 就交由它来处理.
来源: http://www.jianshu.com/p/16d4170b9d90