我可以在构造函数中使用带参数的 ZF3 MVC 框架控制器吗?

Can I have a ZF3 MVC Framework Controller with parameters in the constructor?

我有一个带有两个端点的控制器的 Zend Framework 3 MVC 应用程序。两者都需要访问相同的 class。看起来最好的方法是将此 class 的实例作为控制器 class 的 属性 的实例,如下所示:

class IndexController extends AbstractActionController
{
    /**
     * var Utility $utility
     */
    protected $utility;


    public function __construct(Utility $utility) 
    {
        $this->utility = $utility;
    }

    public function indexAction()
    {
        $this->utility->doA('param1');
        return new ViewModel();
    }

    public function otherAction()
    {
        $results = $this->utility->validateRequest($this->request);
        if ($results) 
        {
            return new ViewModel();
        } 
        else 
        {
            throw new Exception('Invalid request');
        }
    }
}

但是,我不知道如何将参数传递给构造函数,因为我不知道 Zend Framework "makes" 它在哪里。

Zend Framework 使用了一个名为 Dependency Injection. This is based on the D in SOLID, dependency inversion 的概念。除了理论,您需要在 modules.config.php 中为您的控制器创建一个自定义工厂。您还需要为 class calld Utility 创建一个工厂。

所以首先,您可能使用类似于 composer create-project -sdev zendframework/skeleton-application 的命令创建了您的项目。如果这样做,您可能没有最新版本的服务管理器。查看文件 vendor/bin/generate-factory-for-class 是否存在。如果没有,执行composer update zendframework/zend-servicemanager将其添加到那里。

现在让我们为实用程序创建一个工厂 class。让我们假设它在 module/Application/src/Service/Utility.php 中并且具有命名空间 Application\Service。您只需键入 vendor/bin/generate-factory-for-class Application\Service\Utility > module/Application/src/Service/UtilityFactory.php。如果您查看该文件,您可以看到:

public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
    return new Utility();
}

现在让我们用 vendor/bin/generate-factory-for-class Application\Controller\IndexController > module/Application/src/Controller/IndexControllerFactory.php 对控制器做同样的事情。打开这个工厂,看它复杂一点。

public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
    return new IndexController($container->get(\Application\Service\Utility::class));
}

$container 是你的依赖注入容器。它在调用时在这些工厂中执行 __invoke 命令。

还有一件事要做。您需要编辑 module.config.php。替换行

'controllers' => [
    'factories' => [
        Controller\IndexController::class => InvokableFactory::class,
    ],
],

'controllers' => [
    'factories' => [
        Controller\IndexController::class => Controller\IndexControllerFactory::class,
    ],
],

现在将以下部分添加到配置中:

'service_manager' => [
    'factories' => [
        Service\Utility::class => InvokableFactory::class,
    ],
],

那么你的控制器应该可以工作了。