Bind and save form to collection field using array / Doctrine2
I have two objects
Room.php
/**
* @ORM\Table(name="room")
* @ORM\Entity(repositoryClass="Ahsio\StackBundle\Repository\RoomRepository")
*/
class Room
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
// ...
/**
* @ORM\OneToMany(targetEntity="Ahsio\StackBundle\Entity\Workstation", mappedBy="room", cascade={"persist", "remove"}, orphanRemoval=true)
*/
protected $workstations;
and workstation .php
/**
* @ORM\Table(name="workstation")
* @ORM\Entity(repositoryClass="Ahsio\StackBundle\Repository\Workstation")
*/
class Workstation
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity="Ahsio\StackBundle\Entity\Room")
* @ORM\JoinColumn(name="room_id", referencedColumnName="id", nullable=false)
*/
private $room;
// ...
I added a room type with a collection field to add / update / remove workstations
RoomType.php
class RoomType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('id', 'hidden', array(
'read_only' => true,
))
// ....
->add('workstations', 'collection', array(
'type' => new WorkstationType(),
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
))
;
}
// ...
}
Workstation type is a simple two-field ( id
and number
).
The problem is when I try to bind the RoomType for an existing room (which contains two workstations id (1 and 2)) with the following array (which only contains one of the two workstations):
array(4) {
["id"]=> string(1) "3"
["workstations"]=> array(1) {
[0]=> array(2) {
["id"]=> int(1)
["number"]=> int(200)
}
}
Update well done, workstation for id = 2 removed. But when I try to remove all workstations for a given room using:
array(4) {
["id"]=> string(1) "3"
["workstations"]=> array(0) {
}
The workstations are still there. The binding I did is well done, this is what I got when I created $ form-> getData () after binding my $ -form using the last given array:
object(Ahsio\StackBundle\Entity\Room)#229 (4) {
["id":protected]=> string(1) "3"
["name":protected]=> string(20) "first room (updated)"
["description":protected]=> string(39) "This first room is an old one (updated)"
["workstations":protected]=> array(0) {
}
}
So, there are no workstations for the refurbished room. Can anyone tell me why my workstations are not deleted when I save this last linked room?
Here is some of my controller code that I'm using to test the upgrade ...
// The Room $id is given ...
$roomArray = array(
'id' => $id,
'name' => 'first room (updated)',
'description' => 'This first room is an old one (updated)',
'workstations' => array(),
);
$form = $this->createForm(new RoomType(), $room);
$form->bind($roomArray);
if ($form->isValid()) {
$em = $this->getDoctrine()->getEntityManager();
$em->persist($room);
$em->flush();
}
source to share
I think persist
it shouldn't be called when trying to update and delete objects / related objects.
You should probably try calling:
$em->merge($room);
before binding to form data. Thus, you will restore data from the database, and orphanRemoval
- do the rest.
Also, shouldn't you bind
your form with Request
, not with a data object?
source to share