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

ZF2: change view script from controller factory

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

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

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

编辑:

@Saeven 建议发布一些代码。此刻,我决定在controller factory中创建ViewModel,做相应的准备,注入到controller中。但我不确定这是好事。

帮手:

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');
        }
    }
}

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

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

我发现 FormViewHelpers 的想法对我来说并不是很好,因为它增加了不必要的复杂性和层次结构,因为我的 FormViewHelpers 所做的只是将调用直接传递给服务或映射器。只是依赖注入服务(或映射器)和控制器的形式对我来说就很好。 FormViewHelpers,如果(!)有相当多的逻辑要放入,原则上不是一个坏主意。

啊,顺便说一句,@yourcommonsense 在 www.phpdelusions.net 上有一篇很棒的文章描述了(不)正确使用 try 和 catch 块。它的主要信息是当你有特定的场景来恢复错误时使用 try... catch... 。否则 PHP 本身就很好用错误报告。

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