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();
, Я предполагаю, что это не лучший метод, но он работает.
На твоем месте я бы тоже сделал следующее.
Из вашего поста не понятно, почему вы используете форму
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 \ 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()]);