对Laravel广泛使用的外观存在一些批评[见下文],这似乎是一种反模式,例如。
单身“外墙”唯一的优势在于它们相对“容易” 使用“,但从这种快捷方式引入的技术债务很难 甚至估计。
示例代码:
$value = Cache::get('key');
所以,使用上面的示例代码,如果我们不使用外观,任何人都可以告诉我如何用PHP编写这些代码吗?
答案 0 :(得分:6)
免责声明:我不一定同意外墙不好或反模式
“更好”的方法是使用dependency injection。例如,如果这是您的控制器:
public function __construct(\Illuminate\Cache\Repository $cache){
$this->cache = $cache;
}
public function doSomething(){
$value = $this->cache->get('key');
}
或者你可以只用一种方法做同样的事情:
public function doSomething(\Illuminate\Cache\Repository $cache){
$value = $cache->get('key');
}
请注意,我们不是类型提示这里的外观类,而是底层框架类。您可以找到这些类的列表in the docs。
答案 1 :(得分:2)
$app['cache']->get('key');
您是否计划在Laravel框架之外移动Laravel代码库?如果没有,请在我看来忽视这些评论,因为这是Facades唯一值得注意的缺点。
但是如果你想继续沿着这条路走下去,那么本文就有一个可以帮助你的例子。 http://programmingarehard.com/2014/01/11/stop-using-facades.html
答案 2 :(得分:2)
我认为Laravel确实是正确的,因为它们实际上只是类的别名,它们实际上是从IoC容器中解析底层类的代理。这在尝试测试可能使用它们的代码时缓解了大多数问题。从IoC容器中自己解决它们实际上只是在做Laravel已经在做什么,而在我看来牺牲了代码的可读性。
在测试的情况下,可以使用Cache::shouldReceive('someFunction')->...
从设计的角度来看,您可以通过修改服务提供程序来交换实现,以便在使用外观从IoC容器解析时,选择优先于默认实现的实现。这应该给你提供与依赖注入相同的优点,同时保持代码的可读性。
我认为这里的主要问题是传统意义上的这些不是外观,这会导致很多混乱。
答案 3 :(得分:1)
由于您已经标记了单元测试,因此您应该记住,像Laravel这样的静态访问外墙使得完成单一测试的隔离原则非常困难。
存根或模拟静态访问的类或方法是不可能的(据我所知),因为你需要为它提名。
您可能遇到的另一个问题是,您是否需要更改应用程序缓存的方式。虽然你可以完全依赖Laravel,但这很好,但是在你需要改变的那一刻,你将不得不寻求所有Cache::get('key')
次出现才能重构。
正如@lukasgeiter所指出的,更好的方法是通过依赖注入容器(例如Pimple)使用依赖注入。