我有一个Zend Framework 3 MVC应用程序,带有两个端点的控制器。两者都需要访问同一个类。看起来这样做的最好方法是将这个类的实例作为控制器类的属性,如下所示:
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在哪里“制作”它。
答案 0 :(得分:1)
Zend Framework使用名为Dependency Injection的概念。这基于SOLID中的D,dependency inversion。除了理论之外,您还需要在modules.config.php中为控制器创建自定义工厂。您还需要为class calld Utility创建一个工厂。
首先,您可能使用类似于composer create-project -sdev zendframework/skeleton-application
的命令创建项目。如果您这样做,您可能没有最新版本的Service Manager。查看文件vendor/bin/generate-factory-for-class
是否存在。如果没有,请执行composer update zendframework/zend-servicemanager
将其添加到那里。
现在让我们为实用程序类创建一个工厂。让我们假设它在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,
],
],
然后你的控制器应该工作。