ZF2: изменить сценарий представления из фабрики контроллеров

В 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 ответ

Решение

Пересмотрев мой вопрос чуть менее года спустя, решил поделиться своим опытом, возможно, он кому-нибудь пригодится.

Я пошел на разные сценарии просмотра в зависимости от типа партии. Я создал фабрику, которая создает экземпляр модели представления на основе типа вечеринки. Вполне нормально вводить модель представления из фабрики контроллеров в контроллер. Фактически, если вы создаете фабрику для модели представления, вы можете повторно использовать ее как часть модели представления какого-либо другого модуля, прикрепив ее как дочерний элемент главной ViewModel, Иногда это очень полезно, если вам нужно межмодульное взаимодействие.

Я узнал, что идея FormViewHelpers не очень хорошо в моем случае, потому что это добавляет ненужную сложность и иерархию, потому что все, что мой FormViewHelpers сделал, чтобы передать вызов прямо в службу или маппера. Просто сервис с зависимостями (или маппер) и форма в контроллере сделали для меня хорошо. FormViewHelpers, в принципе не плохая идея, ЕСЛИ (!) есть достаточно логики.

Да, и, кстати, есть замечательная статья @yourcommonsense на www.phpdelusion.net, которая описывает (im) правильное использование блоков try и catch. Это главное сообщение, что использование try... catch... когда у вас есть определенный сценарий для восстановления ошибки. В остальном сам PHP довольно хорош с сообщениями об ошибках.

Вот и все. Удачи тому, кто в моих предыдущих туфлях.:-)

Другие вопросы по тегам