Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Zend framework2 ZF2,我不知道的依赖项';我一开始不知道_Zend Framework2 - Fatal编程技术网

Zend framework2 ZF2,我不知道的依赖项';我一开始不知道

Zend framework2 ZF2,我不知道的依赖项';我一开始不知道,zend-framework2,Zend Framework2,在我的控制器中,通过服务,我从DB中获得一个小部件名称列表(如图表、日历等)。每个小部件都实现WidgetInterface,并且可能需要其他服务作为其自身的依赖项。每个用户的小部件列表可能不同,因此我不知道我的控制器中需要哪些小部件/依赖项。通常,我使用工厂通过DI放置依赖项,但在这种情况下,我在控制器初始化时不知道依赖项。 我希望避免直接在控制器中使用服务定位器。我如何处理这个问题?我应该得到控制器工厂中小部件的名称列表吗?根据widgets列表获取所有依赖项并将它们放到控制器中 谢谢,汤姆

在我的控制器中,通过服务,我从DB中获得一个小部件名称列表(如图表、日历等)。每个小部件都实现WidgetInterface,并且可能需要其他服务作为其自身的依赖项。每个用户的小部件列表可能不同,因此我不知道我的控制器中需要哪些小部件/依赖项。通常,我使用工厂通过DI放置依赖项,但在这种情况下,我在控制器初始化时不知道依赖项。 我希望避免直接在控制器中使用服务定位器。我如何处理这个问题?我应该得到控制器工厂中小部件的名称列表吗?根据widgets列表获取所有依赖项并将它们放到控制器中

谢谢,汤姆

解决方案

我以一种建议Kwido和Sven Buis的方式解决了我的问题,这意味着,我构建了自己的插件管理器

优点:我不需要在控制器中直接使用服务定位器,并且我有清晰和可扩展的方法来获得不同种类的小部件


谢谢。

这确实是一个有趣的问题。你可以考虑使用插件来进行小部件的加载。 依赖注入是一种很好的做法,但有时由于内容动态,无法实现

另一种方法是制作自己的小部件管理器。然后,该管理器可以加载您需要的特定小部件。小部件管理器可以注入控制器

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()
将立即加载所有小部件;如果您希望对此进行优化,您可以将您的小部件注册为