On my Symfony 2.7.10 project I have an entity form which loads a material object from the database via the queryBuilder.
$builder
->add('size', 'entity', [
'class' => 'AppBundle\Entity\Material',
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('m')
->select('m')
->where('m.idproduct = :idproduct')->setParameter('idproduct', $this->product->getIdProduct())
->groupBy('m.size')
->orderBy('m.id');
},
'choice_label' => 'size',
'expanded' => true,
'constraints' => new NotBlank(),
]);
Additionally I'm pre setting a form field which is dynamically loaded after the users chose a material size. This is done via an EventSubscriber
$builder->addEventSubscriber(new AddEndTermsSubscriber('size', $options['locale']));
The class looks like this:
...
class AddEndTermsSubscriber implements EventSubscriberInterface
{
private $propertySize;
private $locale;
public function __construct($propertySize, $locale)
{
$this->propertySize = $propertySize;
$this->locale = $locale;
}
public static function getSubscribedEvents()
{
return [
FormEvents::PRE_SET_DATA => 'preSetData',
];
}
private function addFormField(FormInterface $form, Material $material)
{
$form->add('endterm', 'entity', [
'class' => 'AppBundle\Entity\MaterialT',
'query_builder' => function (EntityRepository $er) use ($material) {
return $er->createQueryBuilder('t')
->select('mt')
->from('AppBundle:MaterialT', 'mt')
->leftJoin('mt.m', 'm')
->where('m.size = :size')
->setParameter('size', $material->getSize());
},
'expanded' => true,
'mapped' => false,
'required' => false,
'placeholder' => false,
'choice_label' => 'name'.$this->locale,
]);
}
public function preSetData(FormEvent $event)
{
$data = $event->getData();
$form = $event->getForm();
if ($data === null) {
return;
}
$accessor = PropertyAccess::createPropertyAccessor();
$formMaterial = $accessor->getValue($data, $this->propertySize);
$material = ($formMaterial) ? $formMaterial : new Material();
$this->addFormField($form, $material);
}
}
Via an ajax Action I'm loading the form field for endTerms after the user selected the material.
After the form is submitted I'm storing the material entity and the selected endTerm in the session and redirect to the next form step:
if ($form->get('size')->getData() != null &&
$request->request->get('endterm') != null) {
$request->getSession()->set('token/size', $form->get('size')->getData());
$idEndterm = $request->request->get('endterm');
$endterm = $this->getDoctrine()->getRepository('AppBundle:MaterialT')
->createQueryBuilder('mt')
->leftJoin('mt.m', 'm')
->where('m.id = :id')
->setParameter('id', $idEndterm)
->getQuery()
->getSingleResult();
$request->getSession()->set('token/endterm', $endterm);
//...
}
The problem: The user should have the possibility to edit his configuration, so on the next step he can "edit his configuration" and go back which I do by redirecting to the above action with the form.
public function materialDetailsAction(Request $request)
{
$material = new Material();
$product = $request->getSession()->get('token/product');
$form = $this->createForm(new MaterialType($product), $material, ['locale' => $request->getLocale()]);
//...
}
How can I achieve, that the stored session values are getting prefilled to the form?
Is the best practise to route them via the $options parameter to the form and then do some if else validation ?
Any hints for a solution or how to do better are warmly welcome. Thanks