Zend framework2 ZF2,我不知道的依赖项';我一开始不知道
在我的控制器中,通过服务,我从DB中获得一个小部件名称列表(如图表、日历等)。每个小部件都实现WidgetInterface,并且可能需要其他服务作为其自身的依赖项。每个用户的小部件列表可能不同,因此我不知道我的控制器中需要哪些小部件/依赖项。通常,我使用工厂通过DI放置依赖项,但在这种情况下,我在控制器初始化时不知道依赖项。 我希望避免直接在控制器中使用服务定位器。我如何处理这个问题?我应该得到控制器工厂中小部件的名称列表吗?根据widgets列表获取所有依赖项并将它们放到控制器中 谢谢,汤姆 解决方案 我以一种建议Kwido和Sven Buis的方式解决了我的问题,这意味着,我构建了自己的插件管理器 优点:我不需要在控制器中直接使用服务定位器,并且我有清晰和可扩展的方法来获得不同种类的小部件Zend framework2 ZF2,我不知道的依赖项';我一开始不知道,zend-framework2,Zend Framework2,在我的控制器中,通过服务,我从DB中获得一个小部件名称列表(如图表、日历等)。每个小部件都实现WidgetInterface,并且可能需要其他服务作为其自身的依赖项。每个用户的小部件列表可能不同,因此我不知道我的控制器中需要哪些小部件/依赖项。通常,我使用工厂通过DI放置依赖项,但在这种情况下,我在控制器初始化时不知道依赖项。 我希望避免直接在控制器中使用服务定位器。我如何处理这个问题?我应该得到控制器工厂中小部件的名称列表吗?根据widgets列表获取所有依赖项并将它们放到控制器中 谢谢,汤姆
谢谢。这确实是一个有趣的问题。你可以考虑使用插件来进行小部件的加载。 依赖注入是一种很好的做法,但有时由于内容动态,无法实现 另一种方法是制作自己的小部件管理器。然后,该管理器可以加载您需要的特定小部件。小部件管理器可以注入控制器
interface UserWidgetServiceInterface
{
public function __construct(array $widgets);
public function getWidget($name);
}
编辑:
正如您在上面所看到的,@kwido的想法是一样的。为您的小部件创建自己的管理器,就像某种服务管理器一样
class WidgetManager extends AbstractPluginManager
请看:。因此,通过这种方式,您可以插入WidgetManager,并仅从该管理器中检索小部件作为您的函数:validatePlugin
,检查获取的实例是否正在使用WidgetInterface
。请记住,您仍然可以调用父ServiceManager
或者保持简单,为您的控制器构建一个插件,将您的小部件名称映射到服务。然后,该插件可以使用serviceLocator/Manager检索您的小部件,无论它们是由工厂创建的还是可调用的工厂创建的。因此,您不直接注入所有小部件,而是在请求时才获取它们。一些非常简单的事情:
protected$map=[
//插件中的小部件名称=>要从serviceManager调用的名称或类
'Charts'=>Widget\Charts::class,
];
公共函数加载($name)
{
如果(数组\键\存在($name,$this->map)){
返回$this->getServiceManager()->get($this->map[$name]);
}
返回null;
}
注入所有的小部件可能对你的性能有害,所以你可能会考虑其他一些事情,比如当你的小部件的列表增长时,处理你的请求的时间也会变小。
希望这对您有所帮助,并将您推向某个方向。我将使用单独的服务并将其注入控制器
interface UserWidgetServiceInterface
{
public function __construct(array $widgets);
public function getWidget($name);
}
控制器工厂
class MyControllerFactory
{
public function __invoke(ControllerManager $controllerManager, $name, $requestedName)
{
$serviceLocator = $controllerManager->getServiceLocator();
$userWidgetService = $serviceLocator->get('UserWidgetService');
return new MyController($userWidgetService);
}
}
然后,加载小部件的逻辑将移动到UserWidgetServiceFactory
public function UserWidgetServiceFactory
{
public function __invoke(ServiceManager $serviceLocator, $name, $requestedName)
{
$userId = 123; // Load from somewhere e.g session, auth service.
$widgetNames = $this->getWidgetNames($serviceLocator, $userId);
$widgets = $this->loadWidgets($serviceManager, $widgetNames);
return new UserWidgetService($widgets);
}
public function getWidgetNames(ServiceManager $sm, $userId)
{
return ['foo','bar'];
}
public function loadWidgets(serviceManager $sm, array $widgets)
{
$w = [];
foreach($widgets as $widgetName) {
$w[$widgetName] = $sm->get($widgetName);
}
return $w;
}
}
调用loadWidgets()
将立即加载所有小部件;如果您希望对此进行优化,您可以将您的小部件注册为