ZF2:从控制器工厂更改视图脚本

时间:2016-05-23 10:43:27

标签: zend-framework zend-framework2 zend-controller

在ZF2中,我有2个助手。帮助器有一个表单和一个映射器来处理数据库交互。我使用控制器工厂将这些助手传递给控制器​​。控制器处理作为个人或组织的一方的电话和地址。由于聚会是个人或组织,因此它具有不同的数据,因此控制器工厂还将具有聚会特定数据的对象:PersonObject或OrganizationObject传递给控制器​​。

两个派对类型的2个助手是相同的。但是在视图脚本中,我想显示特定于聚会的数据,这是我的问题:我需要根据控制器工厂传递给控制器​​的对象来更改视图脚本。我想过有两个不同的控制器,但这是一个过度杀伤:视图脚本是90%相同,除了从数据库到派对对象的10%派对特定信息。

如何从控制器工厂更改视图脚本?通过更改此处,我的意思是与派对特定数据略有不同的html布局。

编辑:

@Saeven建议发布一些代码。目前,我决定在控制器工厂中创建ViewModel,相应地准备它,并将其注入控制器。但我不确定它是不是很好。

帮助者:

class ContactMechanismRegistrationViewHelper extends AbstractRegistrationViewHelper
{
    public function __construct(
        FormInterface $form,
        ContactMechanismMapperInterface $contactMechanismMapper
    ) {
        $this->form = $form;
        $this->mapper = $contactMechanismMapper;
    }

    public function saveToDb()
    {
        $this->mapper->save(
            $this->form->get('contactMechanismFieldset')->getObject(),
            $this->form->get('partyFieldset')->getObject()
        );
    }
}

助手工厂:

class ContactMechanismRegistrationViewHelperFactory implements FactoryInterface, MutableCreationOptionsInterface
{
    use MutableCreationOptionsTrait;

    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $serviceManager = $serviceLocator->getServiceLocator();
        $formElementManager = $serviceManager->get('FormElementManager');

        if (in_array('phone', $this->creationOptions)) {
            return new ContactMechanismRegistrationViewHelper(
                $formElementManager
                    ->get('Parties\Forms\Forms\ContactMechanisms\PhoneRegistrationForm'),
                $serviceManager
                    ->get('Parties\Mappers\ContactMechanisms\PhoneMapper')
            );
        } elseif (in_array('address', $this->creationOptions)) {
            return new ContactMechanismRegistrationViewHelper(
                $formElementManager
                    ->get('Parties\Forms\Forms\ContactMechanisms\AddressRegistrationForm'),
                $serviceManager
                    ->get('Parties\Mappers\ContactMechanisms\AddressMapper')
            );
        } else {
            throw new ServiceNotCreatedException('wrong option type specified');
        }
    }
}

使用帮助程序的控制器:

class PartyDetailsController extends AbstractActionController
{
    protected $phoneViewHelper;
    protected $addressViewHelper;
    protected $partyViewModel;

    public function __construct(
        ContactMechanismRegistrationViewHelper $phoneViewHelper,
        ContactMechanismRegistrationViewHelper $addressViewHelper,
        ModelInterface $viewModel
    )
    {
        $this->phoneViewHelper = $phoneViewHelper;
        $this->addressViewHelper = $addressViewHelper;
        $this->viewModel = $viewModel;
    }

    public function indexAction()
    {
        $request = $this->getRequest();
        if ($request->isPost()) {
            $viewHelperForFormSubmission = $this->getViewHelperForFormSubmission(
                $request->getPost('submitButton')
            );
            $viewHelperForFormSubmission->getForm()->setData($request->getPost());
            $viewHelperForFormSubmission->getForm()->setIsSubmitted(true);
            if ($viewHelperForFormSubmission->getForm()->isValid()) {
                try {
                    $viewHelperForFormSubmission->saveToDb();
                    $viewHelperForFormSubmission->getForm()->resetForm();
                } catch (\Exception $e) {
                    die($e->getMessage());
                }
            } else {
                $viewHelperForFormSubmission->getForm()->highlightInvalidElements();
            }
        }

        return $this->viewModel->setVariables([
            'phoneForm' => $this->phoneViewHelper->getForm(),
            'addressForm' => $this->addressViewHelper->getForm(),
        ]);
    }

    protected function getViewHelperForFormSubmission($submitValue)
    {
        if ($submitValue == 'phone') {
            return $this->phoneViewHelper;
        } elseif ($submitValue == 'address') {
            return $this->addressViewHelper;
        } else {
            throw new \Exception('invalid submit argument');
        }
    }
}

1 个答案:

答案 0 :(得分:1)

在不到一年后重新审视我的问题后,决定分享我的经验,也许这对某人有用。

我根据派对类型选择了不同的视图脚本。我所做的是创建了一个工厂,它根据聚会的类型创建一个视图模型的实例。将视图模型从控制器工厂注入控制器是绝对可以的。实际上,如果为视图模型创建工厂,则可以将其作为主要ViewModel的子项附加,将其作为其他模块的视图模型的一部分重用。如果您需要跨模块交互,它有时非常有用。

我发现FormViewHelpers的概念在我的情况下并不是很好,因为它增加了不必要的复杂性和层次结构,因为我FormViewHelpers所做的就是将呼叫直接传递给服务或映射器。只有依赖注入的服务(或映射器)和表单到控制器对我来说没问题。 FormViewHelpers,原则上不是一个坏主意,如果(!)有一些逻辑可以放入。

啊,顺便说一句,@ yourcommonsense在www.phpdelusions.net上有一篇很棒的文章描述了(im)正确使用try和catch块。它的主要信息是,当您有某种恢复错误的方案时,请使用try... catch...。否则PHP本身在错误报告方面非常好。

就是这样。祝我以前的鞋子好运。 : - )