0

在 Zend 3 中,我无法弄清楚注入应该如何工作,让我举一些简单的例子。

比方说,我有

class ToolCollector implements ToolCollectorInterface {
    public function __construct(){}
    public function registerTool(ToolInterface $tool){
        $this->tools[] = $tool;
    }
}

并且

class ToolA implements ToolInterface {
public function __construct(ToolCollectorInterface $mainCollector){$mainCollector->registerTool($this);}
}

所以我期望拥有的

class SomeController extends AbstractActionController {
    public function __construct(ToolCollectorInterface $toolCollector){$this->collector=$toolCollector;}
    public function indexAction(){
        new ToolA;    // <- just call Tool and it will put itself in ToolCollector, this is I want
        new ToolB;    // <- just call Tool and it will put itself in ToolCollector, this is I want
        new ToolC;    // <- just call Tool and it will put itself in ToolCollector, this is I want
    
     return ViewModel(['toolNameList'=>$this->collector->getRegisteredToolNames();])
    }
}

我试图让它如示例所示,当我调用new ToolA它时,它显示错误 500,没有任何描述。

// Next is works
class ToolControllerFactory implements FactoryInterface
{
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        $pm = $container->get(ToolCollector::class);
        return new $requestedName($pm);
    }
}

// Next is not reachable, And I do not know why...
class ToolFactory implements FactoryInterface
{
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        $pm = $container->get(ToolCollector::class);
        return new $requestedName($pm);
    }
}

在 module.config.php

return [
...
'service_manager' => [
    'aliases' => [
            ToolCollectorInterface::class => ToolCollector::class,
        ],
        'factories' => [
            Service\ToolCollector::class => InvokableFactory::class,
        ],
],
'controllers' => [
    'factories' => [
        Controller\App\SomeController ::class => ToolControllerFactory::class,
    ]
],
...
];

有可能做到吗?如何编写工厂使其成为可能?

4

1 回答 1

0

您必须了解使用 IoC 控制反转很容易发现的东西。这Container是处理构建过程和对您需要的实例的引用。

因此,实际上,new在您的内部制作一个既麻烦又无用的indexAction(). 您应该(实际上,您必须这样做以遵循最佳实践)new在您的工厂中为您SomeController拥有的每个依赖项制作任何内容。

所以你会有很多工厂。对于您的控制器、服务、存储库等。每个工厂都有自己的逻辑来构建您需要的对象。

如果没有deps,你可以使用默认InvokableFactory工厂而不用写你的。如果至少有一个 dep,那么您必须编写自己的工厂,并返回您的 Controller / Service / Repository / etc. 类,该类被构建为即用型对象实例。

编码 :

class ToolFactory implements FactoryInterface
{
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        $pm = $container->get(ToolCollector::class);
        return new $requestedName($pm);
    }
}

ToolFactory在您的配置中看不到任何内容,只有一个ToolControllerFactory

'controllers' => [
    'factories' => [
        Controller\App\SomeController ::class => ToolControllerFactory::class,
    ]
],

因此,向您发送 http 500 错误是正常的,因为它不知道您试图用来构建控制器的工厂。

Zend Framework / Laminas 与配置非常相关。您必须遵循原则,然后您才能建立自己的路径以使事情顺利进行。但是,更重要的是,你必须有足够的结构,不会迷失在森林里。

当你开始走路时,一步一步地走,没有改变世界的意愿。梦想是必要的。但是你必须首先处理学习曲线,就像我们任何人一样!

于 2020-08-22T02:19:50.080 回答