Это плохая идея манипулировать Zend-формами с параметрами из контроллера? - PullRequest
0 голосов
/ 18 октября 2019

В настоящее время я создаю формы для своего проекта и уже потратил время на наборы полей. Сначала я должен был выяснить, что вы не можете определить фильтры и валидаторы в наборах полей, а затем, после бесчисленных попыток исправить это в самой форме, я отказался от нее. После смешанного пакета элементов формы fieldset и элементов формы, я решил, что это слишком сложно для простых форм, которые у меня есть.

Так что теперь я решил создать общий класс Form и передать параметры из контроллера вэто для того, чтобы создавать только элементы, которые мне нужны. Это плохая идея? И если да, то почему?

Примерно так:

Контроллер:

$include_title = true
$screening_form->setData($include_title);

Форма

public function __construct($include_title)
{
    if ($include_title)
    {
        $this->add([
           'type' => 'text',
           'name' => 'title',
           'options' => [
                'label' => 'text',
                'placeholder' => 'Test',
            ],
        ]);
    }
}

Ответы [ 2 ]

1 голос
/ 18 октября 2019

Я бы посоветовал сохранить разные формы для разных контекстов, не имея одного большого класса Form для всего вашего приложения. Довольно сложно изменить внешний вид формы, основываясь на данных, переданных через setData (), и это могло быть причиной проблем с наборами полей и проверкой

Если вы хотели иметь «общие» формы, которые можно адаптировать кдругой контекст - это возможно, я бы реализовал это так:

<?php
namespace ConferenceTools\Attendance\Form;

use Zend\Form\Element\DateTime;
use Zend\Form\Element\Submit;
use Zend\Form\Form;

class DateTimeForm extends Form
{
    public function init()
    {
        $this->add([
            'type' => DateTime::class,
            'name' => 'datetime',
            'options' => [
                'label' => $this->getOption('fieldLabel'),
            ],
            'attributes' => [
                'class'=> 'datetimepicker-input',
                'id' => "dtpicker",
                'data-toggle' => "datetimepicker",
                'data-target' => "#dtpicker",
                'autocomplete' => 'off',
            ],
        ]);
    }
}

Это общее использование формы даты и времени в этом проекте: https://github.com/conferencetools/attendance-module/blob/master/src/Form/DateTimeForm.php

Различия в вашей формевызов $this->getOption('fieldLabel'), это лучший способ передачи параметров в форму, чем использование конструктора. Он также создает форму в методе init вместо конструктора, это важно для использования поля параметров и любых пользовательских элементов формы, которые не будут доступны, пока класс не будет полностью создан.

Длячтобы это работало правильно, вам нужно извлечь его из FormPluginManager (имя службы: 'Zend \ Form \ FormElementManager'), который является стандартным локатором службы. Вы можете вставить это в свой контроллер на его фабрике и затем использовать его следующим образом:

// in controller method
$form = $this->formElementManager->get(FormName::class, ['fieldLabel' => 'Arrival time']);

Это не совсем то, как я делаю это в проекте, связанном выше;вместо того, чтобы вводить formElementManager в каждый контроллер, который в этом нуждался, я создал плагин контроллера, который делает его доступным в каждом контроллере. (Код такой же, просто в плагине)

0 голосов
/ 22 октября 2019

Хотя user999305 является правильным (и заслуживает того, чтобы его пометили как решение), учитывая ваш комментарий и недоразумение, я хотел бы привести вам расширенный пример того, что он сказал.

Давайте вамимеют следующую ситуацию:

  • Модуль : FormModule
  • Контроллер : FormController
  • Форма : ComposedForm

В контроллере у вас есть два действия, withTitleAction и withoutTitleAction. Оба используют ComposedForm. Поскольку вам нужно ComposedForm в вашем FormController, вам нужно создать его экземпляр с помощью FormPluginManager (вы можете прочитать об этом в документации )

Теперь у вас есть два вариантакак получить форму в вашем контроллере:

  • вы получаете ее через плагин контроллера (как предложено в конце user999305, и что на самом деле является разумной идеей)
  • вы вводитеFormPluginManager в вашем контроллере

Inject FormPluginManager в контроллере

Прежде всего, вы должны создать фабрику для контроллера:

Контроллер/FormControllerFactory.php

namespace FormModule\Controller;

use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;

class FormControllerFactory implements FactoryInterface {

    public function __invoke(ContainerInterface $container, $requestedName, array $options = null) {
        $formPluginManager = $container->get('FormElementManager');
        return new FormController($container, $options);

    }

}

Необходимо обновить конфигурацию модуля, чтобы приложение знало, как создать контроллер

module.config.php

'controllers' => [
    'factories' => [
        Controller\FormController::class => Controller\FormControllerFactory::class
    ]
],

А теперь просто обновите контроллер, чтобы получить новый параметр:

Controller / FormController.php

namespace FormModule\Controller;

use Zend\Form\FormElementManager;
use Zend\Mvc\Controller\AbstractActionController;

class FormController extends AbstractActionController {

    private $formManager;

    public function __construct(FormElementManager $formManager) {
        $this->formManager = $formManager;

    }
}

Сейчас, выполните два действия:

Controller / FormController.php

public function withTitleAction(){
    $options = ['hasTitle' => true];
    $form = $this->formManager->get(\FormModule\Form\ComposedForm::class, $options);
}

public function withoutTitleAction(){
    $options = ['hasTitle' => false];
    $form = $this->formManager->get(\FormModule\Form\ComposedForm::class, $options);
}

Наконец, ваша форма:

Form / ComposedForm.php

namespace FormModule\Form;

use Zend\Form\Form;
use Zend\InputFilter\InputFilterProviderInterface;

class ComposedForm extends Form {

    public function __construct($name = null, $options = []) {
        // DO NOT FORGET THIS
        parent::__construct($name, $options);

        // The constructor is not really needed, unless you have some
        // dependencies or you have to do something particular, like
        // setting the hydrator, form attributes, form object, ...

    }

    public function init() {
        parent::init();

        if ($this->getOption('hasTitle')) {
            $this->add([
                'type' => 'text',
                'name' => 'title',
                'options' => [
                    'label' => 'text',
                    'placeholder' => 'Test',
                ],
            ]);
        }

    }

}

Надеюсь, это поможет вам

...