laravel的外墙为什么表现得像个单例?

时间:2018-11-21 13:30:03

标签: php laravel

我知道laravel使用外墙。但基本上我无法绕开它为什么要使用它。让我们看一下文件外观类。为什么在已经拥有FileSystem类的情况下将File类作为门面?我们不能在代码中写这样的东西吗?

$file = new \Illuminate\FileSystem();
$path = $file->get(public_path("test.txt"));

但是laravel决定使用File Facade类,之后我可以编写如下内容:

$path = File::get(public_path("test.txt")); 

美女住在哪里?如果您查看外观模式,当您可以使用两行外观进行操作时,它使您可以更轻松地进行大型工作并且不使用10行代码,但是laravel的外观使其难以理解。

难道是因为他们做了门面课,所以它像单身汉一样工作,这是它的神奇之处吗?但是,为什么单身人士会令人惊奇?

我不明白laravel立面的主意是什么。

1 个答案:

答案 0 :(得分:2)

Laravel 具有与 Facade 设计模式相似的功能,也称为 Fades 。这个名称可能会使您感到困惑,因为Laravel中的外墙无法完全实现Facade设计模式。根据{{​​3}}

外观为应用程序的服务容器中可用的类提供了“静态”界面。

因此,Facade将使我们能够使用界面,而不必担心其背后的实际实现。 让我们以Laravel Cache系统为例。 当我们致电$items = Cache::get('items:popular');

在这里,我们借助Cache Facade从缓存中检索项目。

所有外观类都是从基础外观类扩展的。只有一种方法必须在每个Facade类中实现: getFacadeAccessor(),该方法返回IoC容器内的唯一服务名称。因此,它必须返回一个字符串,然后将其解析出IoC容器。

这是 Illuminate \ Support \ Facades \ Cache 门面类的源代码:

<?php 
namespace Illuminate\Support\Facade;
class Cache extends Facade 
{
    protected static function getFacadeAccessor()
    {
        return 'cache';
    }
}

似乎我们正在调用 Cache 类的静态方法get(),但是正如我们所看到的,中没有这样的 static 方法缓存类。这里的方法get()实际上存在于容器内部的服务中。所有的魔法都隐藏在基本的 Facade 类中。

Facade 类中,我们有__callStatic()方法。每次调用外观上不存在的静态方法时,都会触发__callStatic()。因此,在调用Cache::get('items:popular')之后,我们进入了此方法,然后借助getFacadeRoot()方法在IoC容器中解析出外观背后的服务实例。该方法的代码是

public static function __callStatic($method, $args)
{
    $instance = static::getFacadeRoot();

    if (! $instance) {
        throw new RuntimeException('A facade root has not been set.');
    }

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

方法getFacadeRoot()返回外观背后服务对象的实例。在这种情况下,它最终指向 CacheManager 类。在 CacheManager 类中,我们有一个getDefaultDriver()方法,该方法将从.env文件中获取默认的缓存配置。

public function getDefaultDriver()
{
    return $this->app['config']['cache.default'];
}

获取默认缓存配置后,使用__call()的PHP魔术方法尝试在默认缓存(redis,数据库,memcached)的 Concrete Class 上调用get()方法等)。

因此,如果默认缓存发生更改,我们对$items = Cache::get('items:popular');的原始调用将不会更改。大多数人将数据库用作开发的缓存,将 redis 内存缓存用作后端。 Laravel Facades 的工作是找出要执行哪些操作才能从缓存中获取价值。例如。 redis get()实现是

public function get($key)
{
    $value = $this->connection()->get($this->prefix.$key);

    return ! is_null($value) ? $this->unserialize($value) : null;
}

遭到巨灾get()实现是

public function get($key)
{
    $value = $this->memcached->get($this->prefix.$key);

    if ($this->memcached->getResultCode() == 0) {
        return $value;
    }
}

类似地,您可以另一个缓存具体类。 Laravel 将为您决定要调用的具体实现方式。