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

Zend framework ZF2:从控制器工厂更改视图脚本,zend-framework,zend-framework2,zend-controller,Zend Framework,Zend Framework2,Zend Controller,在ZF2中,我有两个助手。助手有一个表单和一个映射器来处理数据库交互。我使用控制器工厂将这些助手传递给控制器。控制器处理个人或组织的一方的电话和地址。由于参与方是个人或组织,因此它具有不同的数据,因此控制器工厂还将包含参与方特定数据的对象PersonObject或OrganizationObject传递给控制器 两种参与方类型的2个助手相同。但是在视图脚本中,我想显示特定于参与方的数据,这是我的问题:我需要根据控制器工厂传递给控制器的对象更改视图脚本。我曾考虑过使用两个不同的控制器,但这是一种过

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

两种参与方类型的2个助手相同。但是在视图脚本中,我想显示特定于参与方的数据,这是我的问题:我需要根据控制器工厂传递给控制器的对象更改视图脚本。我曾考虑过使用两个不同的控制器,但这是一种过分的做法:视图脚本90%相同,除了10%的特定于参与方的信息从数据库输入到参与方对象中

如何从控制器工厂更改视图脚本?这里所说的更改,是指使用特定于参与方的数据略微不同的html布局

编辑:

@萨科齐甚至建议发布一些代码。此时,我决定在控制器工厂中创建
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');
        }
    }
}

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

我选择了不同的视图脚本,这取决于派对类型。我所做的是创建了一个工厂,它根据参与方的类型创建视图模型的实例。将视图模型从控制器工厂注入控制器是完全可以的。事实上,如果为视图模型创建工厂,则可以将其作为其他模块视图模型的一部分重新使用,方法是将其作为主视图模型的子视图进行附加。如果您需要跨模块交互,它有时非常有用

我发现,
FormViewHelpers
的想法在我的案例中并不是很好,因为它增加了不必要的复杂性和层次结构,因为我的
FormViewHelpers
所做的只是将呼叫直接传递给服务或映射程序。只需将依赖注入服务(或映射器)和表单注入控制器就可以了<如果(!)需要加入相当多的逻辑,那么code>formviewerhelpers原则上是个不错的主意

啊,顺便说一句,@yourcommonsense在www.phpdelusions.net上有一篇很棒的文章,描述了try-and-catch块的正确使用。它的主要信息是使用
try。。。当您有恢复错误的特定场景时,捕获…
。否则,PHP本身在错误报告方面相当出色


就这样。祝我的前任好运。:-)

请包括您的助手的代码,以及您如何使用它。@Saeven,嘿,谢谢您的回复。问题是,这将有很多代码很难理解。这就是我一直用文字解释的原因。只需发布你的助手和任何构建它的工厂。您的代码将比您的段落多出100倍:)