Crisp 确实为您的问题提供了有效的答案,但我建议更进一步。服务定位器的注入使您的视图助手与框架和服务定位器模式紧密耦合,并且很容易受到攻击,因为应用程序中的每一段代码都可以修改服务定位器中的每个服务。
There 是直接注入依赖项的原因 http://blog.ircmaxell.com/2012/08/object-scoping-triste-against-service.html,因此您只依赖于您的依赖项,并且不再实现此反模式。我们假设您的视图助手取决于MyModule\Model\MyTable
,那么视图助手的构造函数将如下所示:
namespace MyModule;
use MyModule\Model\MyTable;
use Zend\View\Helper\AbstractHelper;
class MyViewHelper extends AbstractHelper
{
protected $table;
public function __construct(MyTable $table)
{
$this->table = $table;
}
}
正如您所指出的,您只需注入您的MyTable
now:
namespace MyModule;
class Module
{
public function getViewHelperConfig()
{
return array(
'factories' => array(
'MyViewHelper' => function($sm) {
$sm = $sm->getServiceLocator(); // $sm was the view helper's locator
$table = $sm->get('MyModule_MyTable');
$helper = new MyModule\View\Helper\MyHelper($table);
return $helper;
}
)
);
}
}
请注意,在视图助手工厂内,您的服务管理器是查看助手的服务管理器,而不是注册表的“主”管理器(另请参阅我之前写的博客文章 http://juriansluiman.nl/en/article/120/using-zend-framework-service-managers-in-your-application). The $sm->getServiceLocator()
为您解决这个问题。
我不确定我是否理解为什么视图工厂方法会影响具有不同名称的不同工厂方法集。
事实并非如此,因此您的代码中可能存在错误。如果上述方法不起作用,请提供有关您的服务管理器配置的更多详细信息,以便我可以更新我的答案。
上述方法的一大优点是您可以使视图助手的单元测试变得非常容易。您可以模拟表网关并专注于视图助手的完整行为。
use MyModule\View\Helper\MyHelper;
public function testHelperusesTable
{
$mock = $this->getMock('MyModule\Model\MyTable');
$helper = new MyHelper($mock);
// Test your $helper now
}