我知道 Laravel 使用门面。但基本上我无法理解他们为什么使用它。让我们来看看也许是 File 门面类。当他们已经有了 FileSystem 类时,为什么他们将 File 类作为外观?我们不能在我们的代码中写这样的东西吗?
$file = new \Illuminate\FileSystem();
$path = $file->get(public_path("test.txt"));
Run Code Online (Sandbox Code Playgroud)
但是 laravel 决定使用 File 门面类,之后我可以写这样的东西:
$path = File::get(public_path("test.txt"));
Run Code Online (Sandbox Code Playgroud)
美在何处?如果您查看外观模式,它会为您提供更轻松的界面来完成大型工作,并且当您可以使用 2 行外观来完成时,它不会使用 10 行代码,但是 Laravel 的外观使其难以理解。
可能是因为他们制作了门面类,使其像单例一样工作,这是它令人惊奇的一面吗?但是为什么单身如此惊人?
我不明白 laravel 的外观是什么想法。
Laravel有一个类似于Facade设计模式的特性,也称为Facades。这个名字可能会让你感到困惑,因为 Laravel 中的 Facades 并没有完全实现 Facade 设计模式。根据文档
Facades 为应用程序的服务容器中可用的类提供“静态”接口。
因此 Facade 将允许我们使用接口而不必担心这些接口背后的实际实现。让我们以 Laravel 缓存系统为例。当我们打电话$items = Cache::get('items:popular');
在这里,我们借助 Cache 外观从缓存中检索项目。
所有外观类都是从基础Facade类扩展而来的。只有一种方法,必须在每个门面类中实现:getFacadeAccessor(),它返回 IoC 容器内的唯一服务名称。所以它必须返回一个字符串,然后从 IoC 容器中解析出来。
这是Illuminate\Support\Facades\Cache门面类的源代码:
<?php
namespace Illuminate\Support\Facade;
class Cache extends Facade
{
protected static function getFacadeAccessor()
{
return 'cache';
}
}
Run Code Online (Sandbox Code Playgroud)
它看起来像我们调用静态方法get()的缓存类,但正如我们已经看到有没有这样的静态的方法缓存类。这里的方法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);
}
Run Code Online (Sandbox Code Playgroud)
方法getFacadeRoot()返回 Facade 后面的服务对象的实例。在这种情况下,它最终指向CacheManager类。在CacheManager类中,我们有一个getDefaultDriver()方法可以从.env文件中获取默认缓存配置。
public function getDefaultDriver()
{
return $this->app['config']['cache.default'];
}
Run Code Online (Sandbox Code Playgroud)
获取默认缓存配置后,使用它的PHP魔术方法__call()尝试调用Concrete Classget()上的方法默认的缓存(Redis的,数据库,分布式缓存等)。
所以$items = Cache::get('items:popular');如果默认缓存发生变化,我们的原始调用不会改变。大多数人使用数据库作为开发缓存,使用redis或memcached作为后端。这将是Laravel外立面的工作,找出哪些行动,以获得从缓存中的值进行。比如redis的get()实现是
public function get($key)
{
$value = $this->connection()->get($this->prefix.$key);
return ! is_null($value) ? $this->unserialize($value) : null;
}
Run Code Online (Sandbox Code Playgroud)
虽然memacached 的get()实现是
public function get($key)
{
$value = $this->memcached->get($this->prefix.$key);
if ($this->memcached->getResultCode() == 0) {
return $value;
}
}
Run Code Online (Sandbox Code Playgroud)
同样,您可以使用另一个缓存具体类。Laravel会为您决定要调用的具体实现。
| 归档时间: |
|
| 查看次数: |
1118 次 |
| 最近记录: |