I can't get to preselect values in a multiselect form element representing a many to many relation.
In my model $admin
I have the proper data : an ArrayCollection containing the correct CampsTypes but in the form I can't get the multiselect to preselect the proper options.
Admins model
/**
* @var ArrayCollection CampsTypes $campstypes
*
* @ORM\ManyToMany(targetEntity="CampsTypes", inversedBy="admins", cascade={"persist"})
* @ORM\JoinTable(name="campstypes_admins",
* joinColumns={@ORM\JoinColumn(name="admins_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="campstypes_id", referencedColumnName="id")}
* )
*/
private $campstypes;
CampsType model
/**
* @var ArrayCollection Admins $admins
*
* @ORM\ManyToMany(targetEntity="Admins", mappedBy="campstypes", cascade={"persist"})
*/
private $admins;
Then I define my form select element as follow
[
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'name' => 'campTypes',
'required' => false,
'options' => [
'object_manager' => $this->getServiceLocator()->get(EntityManager::class),
'target_class' => CampsTypes::class,
'property' => 'title',
'label' => 'Type de camps autorisés',
'instructions' => 'Ne rien sélectionner si edition d\'un super admin',
],
'attributes' => [
'class' => '',
'multiple' => 'multiple',
]
],
And finally here is my action to receive the form
protected function saveAdmin(Admins &$admin, &$form, &$msg)
{
$em = $this->getEntityManager();
/** @var CampTypesService $serviceCampTypes */
$serviceCampTypes = $this->getServiceLocator()->get(CampTypesService::class);
$form->bind($admin);
if ($this->getRequest()->isPost()) {
$data = $this->getRequest()->getPost();
if (empty($data['password'])) {
$form->remove('password');
}
$form->setData($data);
if ($form->isValid()) {
if (isset($data['campTypes'])) {
$ids = $form->get('campTypes')->getValue();
$campsTypes = new ArrayCollection($serviceCampTypes->getCampTypesByIds(array_values($ids)));
foreach ($campsTypes as &$campsType) {
/** @var CampsTypes $campsType*/
$campsType->addAdmin($admin);
}
$admin->setCampTypes($campsTypes);
}
$em->persist($admin);
$em->flush();
$msg = 'Sauvegarde des données effectuée';
return;
}
}
return;
}
I'm getting out of solution to try.
Any idea what I am doing wrong ?
So I made it work !
basically my main problem is that I was not using proper Doctrine naming convention for the fields name of the form.
So I had to reverse engineer my DB into doctrine entities to compare with what I had done to understand where it was not working. And also to set the model in both end (admins in camptype and camptypse in admin) for the whole shabang to work.
Here are the working classes :
Admin form:
[
'type' => ObjectSelect::class,
'name' => 'campstypes',
'required' => false,
'options' => [
'object_manager' => $this->getServiceLocator()->get(EntityManager::class),
'target_class' => CampsTypes::class,
'property' => 'title',
'label' => 'Type de camps autorisés',
'instructions' => 'Ne rien sélectionner si edition d\'un super admin',
],
'attributes' => [
'class' => '',
'multiple' => 'multiple',
]
],
Admin Controller:
protected function saveAdmin(Admins &$admin, &$form, &$msg)
{
$em = $this->getEntityManager();
/** @var CampTypesService $serviceCampTypes */
$serviceCampTypes = $this->getServiceLocator()->get(CampTypesService::class);
$form->bind($admin);
if ($this->getRequest()->isPost()) {
$data = $this->getRequest()->getPost();
if (empty($data['password'])) {
$form->remove('password');
}
$form->setData($data);
if ($form->isValid()) {
if (isset($data['campstypes'])) {
$ids = $form->get('campstypes')->getValue();
$campsTypes = new ArrayCollection($serviceCampTypes->getCampTypesByIds(array_values($ids)));
foreach ($campsTypes as &$campsType) {
/** @var CampsTypes $campsType*/
$campsType->addAdmin($admin);
}
$admin->setCampstypes($campsTypes);
}
$em->persist($admin);
$em->flush();
$msg = 'Sauvegarde des données effectuée';
return;
}
}
return;
}
So by renaming properly the fields of my form and models and setting the data in both end model of the relation I got it to work.