Я пытаюсь понять, как обрабатывать формы при использовании унаследованных типов классов с Symfony (2.8.6).
Я создал [очень] простой пример того, что я пытаюсь сделать ниже. Есть проблемы с этим, но это только для иллюстрации моего вопроса.
Если бы кто-то мог даже указать мне на репозиторий Github или что-то, что показывает что-то подобное, я был бы очень благодарен. Спасибо за ваше время.
Если это мои занятия:
/**
* @ORM\Entity
* @ORM\InheritanceType("SINGLE_TABLE")
* @ORM\DiscriminatorColumn(name="discr", type="string")
* @ORM\DiscriminatorMap("truck" = "Truck", "Car" = "Car", "suv" = "SUV")
*/
abstract class Vechicle {
private $make;
private $model;
private $numberOfDoors;
// getters and setters //
}
class Truck extends Vehicle {
private $offRoadPackage;
private $bedSize;
// getters and setters //
}
class Car extends Vehicle {
private $bodyType;
}
class SUV extends Vehicle {
// no additional fields //
}
тогда что-то вроде этого будет моими типами форм:
class VehicleType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('make')
->add('model')
->add('numberOfDoors');
}
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults(array(
'data_class' => 'MyBundle\Entity\Vehicle'
));
}
}
class TruckType extends VehicleType {
public function buildForm(FormBuilderInterface $builder, array $options) {
parent::buildForm($builder, $options);
$builder
->add('offRoadPackage')
->add('bedSize');
}
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults(array(
'data_class' => 'MyBundle\Entity\Truck'
));
}
}
class CarType extends VehicleType {
public function buildForm(FormBuilderInterface $builder, array $options) {
parent::buildForm($builder, $options);
$builder
->add('bodyType')
}
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults(array(
'data_class' => 'MyBundle\Entity\Car'
));
}
}
class SUVType extends VehicleType {
public function buildForm(FormBuilderInterface $builder, array $options) {
parent::buildForm($builder, $options);
}
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults(array(
'data_class' => 'MyBundle\Entity\SUV'
));
}
}
Это будет немного длинно, но терпите меня. Суть этой идеи в том, что вы имеете дело с вашими формами в массиве. Вы создаете список типов, которые вы повторяете для создания реальных объектов формы. Таким образом, единственное, что вы редактируете, это список типов форм, если вы хотите добавить больше.
В вашем шаблоне вы перебираете все формы, чтобы отобразить их, и оберните их в div, который вы можете скрыть. Затем вы можете добавить элемент select, который управляет частью JavaScript, показывая / скрывая форму выбранного пользователем типа.
После sbumission вы можете проверить, было ли действие размещено на POST и повторить формы, чтобы проверить, какая из них была отправлена и обрабатывать его соответствующим образом.
Ниже сырая непроверенной фрагмент кода:
Контроллер / действие:
class SomeController
{
public function addAction()
{
$types = [
'Form1' => Form1::class,
'Form2' => Form2::class,
'Form3' => Form3::class,
];
// create the forms based on the types indicated in the types arary
$forms = [];
foreach ($types as $type) {
$forms[] = $this->createForm($type);
}
if ($request->isMethod('POST')) {
foreach ($forms as $form) {
$form->handleRequest($request);
if (!$form->isSubmitted()) continue; // no need to validate a form that isn't submitted
if ($form->isValid()) {
// handle the form of your type
break; // stop processing as we found the form we have to deal with
}
}
}
$views = [];
foreach ($forms as $form) {
$views = $form->createView();
}
$this->render('template.html.twig', ['forms' => $views, 'types' => $types]);
}
}
Шаблон:
<select id="types">
{% for type in types|keys %}
<option value="vehicle_type_{{ loop.index }}">{{ type }}</option>
{% endfor %}
</select>
{% for form in forms %}
<div class="form hidden" id="vehicle_type_{{ loop.index }}">
{{ form_start(form) }}
{{ form_widget(form) }}
{{ form_end(form) }}
</div>
{% endfor %}
И, наконец, фрагмент JavaScript, управляющий тем, какая форма отображается / скрывается:
<script>
// On select change hide all forms except for the on that was just selected
$('#types').on('change', function () {
$('.form').addClass('hidden');
$('#' + $(this).val()).removeClass('hidden');
});
</script>
Других решений пока нет …