您的位置:首页 > 编程语言 > PHP开发

Laravel 门面类:Facade简记

2017-07-06 14:43 429 查看
这是另一位大哥写的,感觉写的很好,在此感谢他的分享。这位大哥的这篇文章详细介绍了原理,但是感觉初次看的人可能需要下面这个前期知识储备:

static:: 静态延迟绑定

还有一点就是我的实际代码和他的有点不同,这里再贴一下实际的源码,顺道也再整理一下思路:

这里拿
vendor/laravel/framework/src/Illuminate/Support/Facades/App.php
为例进行介绍:

<?php
namespace Illuminate\Support\Facades;

/**
* 这里顺道记录一个小技巧,在函数前写这样的注释,会被PHPSrorm解析,表示该类所拥有的方法
* @method static string version()
* @method static string basePath()
* @method static string environment()
* @method static bool isDownForMaintenance()
* @method static void registerConfiguredProviders()
* @method static \Illuminate\Support\ServiceProvider register(\Illuminate\Support\ServiceProvider|string $provider, array $options = [], bool $force = false)
* @method static void registerDeferredProvider(string $provider, string $service = null)
* @method static void boot()
* @method static void booting(mixed $callback)
* @method static void booted(mixed $callback)
* @method static string getCachedServicesPath()
*
* @see \Illuminate\Foundation\Application
*/
class App extends Facade
{
/**
* Get the registered name of the component.
*
* @return string
*/
protected static function getFacadeAccessor()
{
return 'app';
}
}


当我们外部这样调用时:

use App;

/App:make('app');


时,根据服务容器的自动依赖注入,(Facade类是App类的抽象类):

<?php

namespace Illuminate\Support\Facades;

use Mockery;
use RuntimeException;
use Mockery\MockInterface;

abstract class Facade{
//先省略其中的代码
}


会自动调用到
App
类,接着就是解释如何像调用静态方法一样调用
App
类中的方法了,根据那位大哥的解释,当我们调用
getFacadeAccessor()
方法时,在
Facades
中并没有该静态方法,那么就会调用PHP的魔术方法:
__callStatic($method,$args)
,下面来看其源码:

public static function __callStatic($method, $args)
{
$instance = static::getFacadeRoot();
//先到这里,下面讲解 static::getFacadeRoot() 这个函数
if (! $instance) {
throw new RuntimeException('A facade root has not been set.');
}

return $instance->$method(...$args);
}


其中的
getFacadeRoot
方法如下:

public static function getFacadeRoot()
{
//注意,最开始时我们的 getFacadeAccessor() 的返回值是 "app"
return static::resolveFacadeInstance(static::getFacadeAccessor());
}


接下来再看
resolveFacadeInstance


protected static function resolveFacadeInstance($name)
{
//如果传入的参数是对象的话,则返回该对象
if (is_object($name)) {
return $name;
}
//如果该类是在项目加载完成后就自动装载的,则返回该类
if (isset(static::$resolvedInstance[$name])) {
return static::$resolvedInstance[$name];
}
//如果没有,就到服务容器中去找
return static::$resolvedInstance[$name] = static::$app[$name];
}


其实简单点来说就是返回该
$name
的实例,接着回到最开始的
__callStatic
函数的剩余部分:

//如果经过上面的`resolveFacadeInstance`函数没有办法获取该类实例的话,那么接下来肯定无法正常运行了,所以这里抛出异常
if (! $instance) {
throw new RuntimeException('A facade root has not been set.');
}
  //就是在这里调用了该类下面的方法,...$args表示该方法可能存在输入参数,可能不存在
return $instance->$method(...$args);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: