zf2/zf3 Увлажнение нескольких наборов полей объектами

Проблема: при использовании $form->bind($object) несколько наборов полей в форме не заполняются / не обрабатываются. Как заполнить 2 разных набора полей в форме 2 разных объекта сущности? У меня есть 2 набора полей: FieldsetA, FieldsetB

Форма RegisterFrom вызывает их в своем методе init()

class RegisterForm extends Form
{
    public function init(){
        $this->add(array(
                'name' => 'service_provider_fieldset',
                'type' => ServiceProviderFieldset::class,   // this is one model/entity
        ));

        $this->add(array(
                'name' => 'location_fieldset',
                'type' => LocationFieldset::class,   // this is a separate model/entity
        ));
}
}

Создание наборов полей: (обратите внимание, закомментированы попытки гидратации)

class ServiceProviderFieldset extends Fieldset
{
    public function init(){
        //parent::__construct($name);
        /*
        $this
        ->setHydrator(new ClassMethodsHydrator(false))
        ->setObject(new ServiceProvider())
        ;
        */

        /*
        $this
        ->setHydrator(new ReflectionHydrator(false))
        ->setObject(new ServiceProvider())
        ;
        */

        $this->add(array(
                'type'=>'Hidden',
                'name'=>'id',
                'options'=>array(
                        'label' => 'Service Provider Id'
                ),
                'attributes'=>array(
                        'id'=>'providerId'
                )
        ));
}
}

контроллер:

    $provider = $this->findServiceProviderById($providerId); // this is set from DB call and correctly creates a Provider() object with populated values.
    $location = $this->findServiceProviderLocationById($locId);
    $form = $formManager->get(RegisterForm::class);
    $form->bind($provider);
    $form->bin($location);
// $form->get('service_provider_fieldset')->bindValues(...);

Посмотреть:

$formElement = $form->get('service_provider_fieldset')->get('email');
etc...

Форма отображается в представлении правильно, НО без заполненных данных.

ПРИМЕЧАНИЕ: НЕ использую Doctrine, но я получаю данные из БД в порядке. ПРИМЕЧАНИЕ. Если я установлю этот флаг 'use_as_base_fieldset' => true, то заполняется 1 из объектов (ServiceProvider), наоборот, если я установлю для полей местоположения значение 'true', то заполняется. Я искал пару часов, методом проб и ошибок, но безуспешно, и я надеюсь, что это просто моя усталость, которая пропустила простой шаг настройки / настройки, чтобы заставить это работать.

Описание: Как вы заполняете 2 или более набора полей двумя или более объектами в форме? Bind(), fieldset->bindValues ​​()?,

Пытался:

$form->get('service_provider_fieldset')->allowObjectBinding(true);
        $form->get('service_provider_fieldset')->allowedObjectBindingClass(\Provider\Form\ServiceProviderFieldset::class);

Это некоторые ссылки, которые близки, но по-прежнему не могут заполнять оба набора полей через отдельные объекты. ZF2 Form Hydration с несколькими объектами и наборами полей https://framework.zend.com/manual/2.4/en/modules/zend.form.collections.html увлажнение нескольких объектов из наборов полей ZF2

Пример коллекций (product/brand/category) подразумевает "одиночную" коллекцию с использованием 'use_as_base_fieldset' => true, которая используется для bind()...?

2 ответа

На вашей веб-странице проверьте имена элементов формы, которые относятся к вашим наборам полей. Они должны быть примерно такими: yourFieldsetName[yourElementName], Если вы просто видите yourElementName, что, скорее всего, означает, что забыл prepare() Ваша форма в сценарии просмотра.

Это именно то, что случилось со мной, и после того, как я prepare() Под воздействием формы все объекты увлажнены без проблем.

ОБНОВЛЕНИЕ = ответ на вопросы комментария: Не решен как таковой. Это плохой дизайн? Примечание. Я использую prepare() в представлении.

Если все работает нормально, ваши 2 объекта должны увлажняться. use_as_base_fieldset Флаг используется в основном для того, чтобы сказать: "Эй, это я (набор полей), вы должны только гидрировать объект данными / извлекать данные из объекта". То, что вы получаете, когда один объект гидратируется, а другой нет, и наоборот, предсказуемо. Довольно сложно сказать, что происходит, не глядя на ваш полный код. Боюсь, что публикация слишком большого количества сообщений также займет время, чтобы понять ответчика, и мой опыт показывает, что такие вопросы обычно остаются без ответа. В таких ситуациях, как ваша, я обычно делаю шаг за шагом в Zend Form и Fieldset s методы, используемые в гидратации / экстракции. я использую \Zend\Debug\Debug::dump($somethingThatYouWantToCheck); die();, Я предполагаю, что это не лучший метод, но он работает.

На твоем месте я бы тоже сделал следующее.

  1. Из вашего поста не понятно, почему вы используете форму init() метод. init() Метод используется, когда вы хотите, например, чтобы некоторые элементы в вашей форме были заполнены из БД (например, <select>). Form работает init() метод, когда некоторые вещи, которые не доступны в __construct() метода пока нет, но только после создания экземпляра формы (не уверен на 100% в этом, перепроверьте это).

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

  3. Если ты не хочешь идти с \Zend\Debug\Debug::dump($somethingThatYouWantToCheck); die(); (это может быть довольно утомительно, я знаю), создайте один набор полей и прикрепите к нему желаемые 2 набора полей. Затем включите этот набор полей в форму и используйте use_as_base_fieldset = true на этом наборе полей (конечно, вам также нужно создать объект, соответствующий этому набору полей, с двумя вложенными объектами, которые прикреплены к вашим текущим наборам полей, и прикрепить объект к набору полей).

Надеюсь, это поможет хоть немного.


Для работы с несколькими объектами вам необходимо:

1. Создайте форму с набором полей для каждого объекта, как вы это сделали.
Вы должны указать имя для каждого набора полей (например, в конструкторе).

2. В каждом наборе полей нам нужно указать гидратор
например: $this->setHydrator(new ClassMethods());

Zend \ Hydrator \ ClassMethods для использования функций получения или
Zend\Hydrator\ArraySerializable для использования метода getArrayCopy.

и разрешить класс объекта:

$this->setAllowedObjectBindingClass(YourClassObject::class);

Вы можете сделать это в методе init в fieldset.


3. Установите гидратор для основной формы:

$this->setHydrator(new ArraySerializable());


4. Теперь в методе контроллера вы можете создать объект Zend\Stdlib\ArrayObject:

$obj = new ArrayObject();

затем добавьте ваши объекты с ключом равным имени fieldset:

$obj->offsetSet("fieldset_name", $your_object);

и тогда вы можете привязать $obj к вашей форме:

$form->bind($obj);


Надеюсь, это поможет. И не забудьте о методе подготовки:

return new ViewModel(["form" => $form->prepare()]);
Другие вопросы по тегам