Проблема: при использовании $ 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
Пример коллекции (продукт / марка / категория) подразумевает «единую» коллекцию с использованием ‘use_as_base_fieldset’ => true, используется для связывания () …?
На вашей веб-странице проверьте имена элементов формы, которые относятся к вашим наборам полей. Они должны быть примерно такими: yourFieldsetName[yourElementName]
, Если вы просто видите yourElementName
, что, скорее всего, означает, что забыл prepare()
Ваша форма в сценарии просмотра.
Это именно то, что случилось со мной, и после того, как я prepare()
Под воздействием формы все объекты гидратировались без проблем.
ОБНОВЛЕНИЕ = ответ на вопросы комментария: Не решен как таковой. Это плохой дизайн? Примечание. Я использую prepare () в представлении.
Если все работает нормально, ваши 2 объекта должны увлажняться. use_as_base_fieldset
Флаг используется для того, чтобы сказать: «Эй, это я (набор полей), вы должны только гидрировать объект данными / извлекать данные из объекта». То, что вы получаете, когда один объект гидратируется, а другой нет, и наоборот, предсказуемо. Довольно сложно сказать, что происходит, не глядя на ваш полный код. Боюсь, что публикация слишком большого количества сообщений также займет время, чтобы понять ответчика, и мой опыт показывает, что такие вопросы обычно остаются без ответа. В таких ситуациях, как ваша, я обычно делаю шаг за шагом в Zend Form
и Fieldset
s методы, используемые в гидратации / экстракции. я использую \Zend\Debug\Debug::dump($somethingThatYouWantToCheck); die();
, Я предполагаю, что это не лучший метод, но он работает.
На твоем месте я бы тоже сделал следующее.
Из вашего поста не понятно, почему вы используете форму init()
метод. init()
Метод используется, когда вы хотите, например, чтобы некоторые элементы в вашей форме были заполнены из БД (например, <select>
). Form
работает init()
метод, когда некоторые вещи, которые не доступны в __construct()
метода пока нет, но только после того, как экземпляр формы создан (не уверен на 100% в этом, перепроверьте это).
Не беспокойтесь о хорошем / плохом дизайне. Дизайн — это очень хорошая вещь, но если у вас небольшая или средняя система, соображения дизайна не влияют на производительность / сложность системы. Но скорее вы потратите действительно много времени, делая все правильно, чем просто делая это, и если это работает хорошо, забывая об этом.
Если ты не хочешь идти с \Zend\Debug\Debug::dump($somethingThatYouWantToCheck); die();
(это может быть довольно утомительно, я знаю), создайте один набор полей и прикрепите к нему желаемые 2 набора полей. Затем включите этот набор полей в форму и используйте use_as_base_fieldset = true
на этом наборе полей (конечно, вам также нужно создать объект, соответствующий этому набору полей, с двумя вложенными объектами, которые прикреплены к вашим текущим наборам полей, и прикрепить объект к набору полей).
Надеюсь, это поможет хоть немного.
Для работы с несколькими объектами вам необходимо:
1. Создайте форму с набором полей для каждого объекта, как вы это сделали.
Ты должен укажите имя для каждого набора полей (например, в конструкторе).
2. В каждом наборе полей нам нужно указать гидратор
например.: $this->setHydrator(new ClassMethods());
Zend \ Hydrator \ методы класса для использования функций геттера или
Zend \ Hydrator \ ArraySerializable для использования метода getArrayCopy.
и разрешить класс объекта:
$this->setAllowedObjectBindingClass(YourClassObject::class);
Вы можете сделать это в в этом метод в 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()]);