我可以在 Controller Factory 中读取来自 GET 的输入吗?

Can I read input from GET inside a Controller Factory?

这个问题不是明确关于 ZF2 的,但我经常从 ZF2 那里得到我的代码的问题。也就是说,我见过的大多数 ZF2 示例都在控制器操作中处理输入。

示例:

class YourController extends AbstractActionController
{

    public function doStuffAction()
    {
        // ZF2's way to get input from $_GET variable
        $product =  $this->getEvent()->getRouteMatch()->getParam('product');

        // Process    
        $processor = (new ProcessorFactory())->getProcessor($product);
        $output = $processor->processInput($data);
    }
}

现在,我 喜欢 Processor 注入我的控制器。不要像我上面那样在控制器内部创建它。但是由于 Processor 依赖于知道 $product,它只能从 $_GET 获得,我看不到任何其他方式。

如果我想将 Processor 注入控制器,我必须将填充 $product 变量的行也移到控制器之外。

如何在不严重破坏 OOP、ZF2 和设计模式的情况下这样做?在我看来,任何与 $_GET 相关的事情都应该在 Controller 内完成,而不是在 ControllerFactory 内完成。除非我能打破这种模式?

如果你只是想应用依赖倒置原则。应用 SOLID 首字母缩略词的 D,只需稍作改动。

class YourController
{

    /**
     * @var ProcessorFactory
     */
    protected $processorFactory;

    public function __construct(ProcessorFactory $processorFactory)
    {
        $this->processorFactory = $processorFactory;
    }

    public function doStuffAction()
    {
        $product =  $this->getEvent()->getRouteMatch()->getParam('product');
        $processor = $this->processorFactory->getProcessor($product);
    }
}

您可以通过输入 I 界面 (SOLID)

来改进
class YourController
{

    /**
     * @var ProcessorFactoryInterface
     */
    protected $processorFactory;

    public function __construct(ProcessorFactoryInterface $processorFactory)
    {
        $this->processorFactory = $processorFactory;
    }

    public function doStuffAction()
    {
        $product =  $this->getEvent()->getRouteMatch()->getParam('product');
        $processor = $this->processorFactory->getProcessor($product);
    }
}

现在,如果您不想让您的控制器负责启动创建过程 (SOLID),您可以将它再拆分一些。

class YourController
{

    /**
     * @var ProcessorInterface
     */
    protected $processor;

    public function __construct(ProcessorInterface $processor)
    {
        $this->processor = $processor;
    }

    public function doStuffAction()
    {
        $processor = $this->processor;
    }
}

class ControllerFactory
{
    /**
     * @var ProcessorFactory
     */
    protected $processorFactory;

    public function  __construct(ProcessorFactory $processorFactory)
    {
        $this->processorFactory = $processorFactory;
    }

    public function create()
    {
        return new YourController($this->processorFactory->getProcessor());
    }
}

class ProcessorFactory
{
    /**
     * @var RouteMatch
     */
    protected $routeMatch;

    public function __construct(RouteMatch $routeMatch)
    {
        $this->routeMatch = $routeMatch;
    }

    public function getProcessor()
    {
        $processor = $this->createProcessor();
        // do stuff
        return $processor;
    }

    protected function createProcessor()
    {
        $product =  $this->routeMatch->getParam('product');

        // create processor

        return $processor;
    }
}

以下代码将为您提供控制器。

$controllerFactory = new ControllerFactory(new ProcessorFactory(new RouteMatch()));
$yourController = $controllerFactory->create();

现在上面的代码是更通用的代码,不适用于 ZF2。一个好的举措是让 ZF2 的服务经理参与进来。

class YourController extends AbstractActionController
{

    /**
     * @var ProcessorInterface
     */
    protected $processor;

    public function __construct(ProcessorInterface $processor)
    {
        $this->processor = $processor;
    }

    public function doStuffAction()
    {
        $processor = $this->processor;
    }
}


class YourControllerFactory implements FactoryInterface
{

    public function createService(ServiceLocatorInterface $controllers)
    {
        $services = $controllers->getServiceLocator();
        $processorFactory = $services->get('ProcessorFactory');
        return new YourController($processorFactory->getProcessor());
    }
}

class ProcessorFactory
{
    /**
     * @var RouteMatch
     */
    protected $routeMatch;

    public function __construct(RouteMatch $routeMatch)
    {
        $this->routeMatch = $routeMatch;
    }

    public function getProcessor()
    {
        $processor = $this->createProcessor();
        // do stuff
        return $processor;
    }

    protected function createProcessor()
    {
        $product =  $this->routeMatch->getParam('product');

        // create processor

        return $processor;
    }
}

class ProcessorFactoryFactory implements FactoryInterface
{

    public function createService(ServiceLocatorInterface $services)
    {
        return new ProcessorFactory($services->get('RouteMatch'));
    }
}

以上 services/controllers 他们的工厂应该在 ServiceManager/ControllerManager

注册
$config = [
    'controllers' = [
        'factories' [
             'YourController' => 'YourControllerFactory',
        ],
    ],
    'service_manager' = [
        'factories' [
             'ProcessorFactory' => 'ProcessorFactoryFactory',
        ],
    ],
];

当请求分派到 YourController 时,ControllerManager returns 一个注入处理器的 YourController 实例。它获得哪个处理器取决于请求(RouteMatch 中的一个参数)。