I am trying to create a filter form with multiple fields, and one of them is a select/drop-down for selecting from a list of Tournaments.
The idea is to make the form reusable so I'm creating a FilterType form class. The Tournament select field is created by embedding a TournamentChoiceType form class which creates an EntityType field using the Tournament entity.
The issue I'm facing is when the form is submitted and I get the submitted data. The $tournamentChoice is a Tournament object (which is OK), but $tournamentId = $tournamentChoice->getId() is returning a Tournament object too, and it should be an integer (the ID columnn).
The mess seems to happen here:
$filterForm->handleRequest($request);
because when I view/dump the raw POST request all seems normal and the filter[tournament][id] is just an integer parameter passed in, as expected.
Here's the code.
Controller:
$em = $this->getDoctrine()->getManager();
$tournamentSelected = $em->getRepository('MyBundle:Tournament')
-> findOneById($id);
$tournamentsList = $em->getRepository('MyBundle:Tournament')
->findAll();
$formInputData = array();
$formInputData['tournament']['data'] = $tournamentSelected;
$formInputData['tournament']['choices'] = $tournamentsList;
formData = array();
$filterForm = $this->createForm(FilterType::class, $formData, array(
'data' => $formInputData
));
$filterForm->handleRequest($request);
if ($filterForm->isSubmitted() && $filterForm->isValid()) {
$formData = $filterForm->getData();
$tournamentChoice = $formData['tournament'];
$tournamentId = $tournamentChoice->getId();
$dateFromChoice = $formData['date_from'];
$dateToChoice = $formData['date_to'];
return $this->redirectToRoute(
'index',
array('tournament' => $tournamentId)
);
}
FilterType form class:
class FilterType extends AbstractType
{
protected $data;
/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => null
));
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$this->data = $options['data'];
...
$builder
->add('tournament', TournamentChoiceType::class, array(
'choices' => $this->data['tournament']['choices'],
'data' => $this->data['tournament']['data']
))
;
...
}
}
TournamentChoiceType form class:
class TournamentChoiceType extends AbstractType
{
protected $data;
protected $choices;
/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'MyBundle\Entity\Tournament',
'choices' => null
));
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$this->data = $options['data'];
$this->choices = $options['choices'];
$builder
->add('id', EntityType::class, array(
'class' => 'MyBundle:Tournament',
'choices' => $this->choices,
'choice_label' => 'name',
'label' => false,
'data' => $this->data
))
;
}
}
Tournament entity class:
class Tournament
{
/**
* @ORM\Column(type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
...
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
...
}
Here's how var_dump($filterForm->getData())
looks like, after a submit:
array (size=4)
'field1' => string 'text' (length=4)
'field2' => string 'text' (length=4)
...
'tournament' =>
object(MyBundle\Entity\Tournament)[631]
private 'id' =>
object(MyBundle\Entity\Tournament)[522]
private 'id' => int 11
private 'name' => string 'tournament1' (length=11)
private ...
...
and here's how var_dump($filterForm->getData())
looks like, after a second submit:
array (size=4)
'field1' => string 'text' (length=4)
'field2' => string 'text' (length=4)
...
'tournament' =>
object(MyBundle\Entity\Tournament)[513]
private 'id' =>
&object(MyBundle\Entity\Tournament)[513]
private 'name' => string 'tournament1' (length=11)
private ...
What's with the object's ID being an object (and not being just an interger), or referencing an object?