zajca
zajca

Reputation: 2418

Symfony form collection not saving reference

I have entity which has multiple Photos:

/**
 * related images
 * @ORM\OneToMany(targetEntity="Photo", mappedBy="entity",cascade={"persist"})
 * @ORM\OrderBy({"uploaded_at" = "ASC"})
 */
private $photos;

Photos have ManyToOne relation with entity

    /**
 * @ORM\ManyToOne(targetEntity="Acme\AppBundle\Entity\Entity", inversedBy="photos")
 * @ORM\JoinColumn(name="entity_id", referencedColumnName="id", onDelete="CASCADE")
 */
private $entity;

all setters and getter are set I'm foliving symfony collection documentation: http://symfony.com/doc/current/reference/forms/types/collection.html

FormType:

             ->add('photos', 'collection', array(
             'type' => new PhotoFormType(),
             'allow_add' => true,
             'by_reference' => false,
             'allow_delete' => true,
             'prototype' => true

         ))

PhotoType:

        $builder
        ->add('title', null, ['label' => 'front.photo.title', 'required' => true])
        ->add('image', 'file', array('required' => false))
    ;

For upload I'm using vichUploadableBundle, Images are save just fine, but entity_id is not save and has null. I don't know what I did miss here.

Upvotes: 4

Views: 5746

Answers (4)

Martin Fasani
Martin Fasani

Reputation: 823

I've went to this also. I think the main problem is that even the main entity has cascade={"persist"} , the child entites do not get the ID when you are creating a new entry. So what I did, that is kind of a hack, but works fine is this.

// $em->persist($entity);  After persisting entity:
foreach ($entity->getPhotos() as $photo) {
    $photo->setEntity($entity);
}

Basically persisting the ID in the childs after their father is created.

But on another point, at least how I understand Doctrine, please correct me if I'm wrong. Try to add an orphanRemoval / fetch additional properties:

FATHER Entity has:

 /**
  * Related images.
  * @ORM\OneToMany(targetEntity="Photo", mappedBy="entity", cascade={"persist"}, orphanRemoval=true, fetch="EAGER")
  * @ORM\OrderBy({"uploaded_at" = "ASC"})
  */

  private $photos;

Upvotes: 3

Julfiker
Julfiker

Reputation: 308

Following would be best solution on this issue so far investigate or research with symfony form component.

FormType:

     ->add("photos",'collection', array(
            'type' => new PhotoFormType(),
            'allow_add' => true,
            'allow_delete' => true,
            'by_reference' => false
))

Entity class

public function addPhoto(Photo $photo)
{
    $photo->setEntity($this);
    $this->photos->add($photo);        
}

public function removePhoto(Photo $photo)
{
    $this->photos->removeElement($photo);
}

Best practice is not to use loop to bind reference entity manually . Remember by_reference must be false. like 'by_reference' => false.

Upvotes: 6

Fire Knight
Fire Knight

Reputation: 91

Run into the same issue, still I remember there is better solution.

You need to specify add and remove functions in the entity with collection.

class Entity
{
    // ...

    public function addPhoto(Photo $photo)
    {
        $this->photos->add($photo);
        $photo->setEntity($this);
    }

    public function removePhoto(Photo $photo)
    {
        $this->photos->removeElement($photo);
    }
}

So in such a case you wouldn't need a loop in the controller. Also if

orphanRemoval=true

is set, no problems with delete.

Upvotes: 4

zajca
zajca

Reputation: 2418

Photo Entity is persisted so I add to controller handler to set for every photo Entity. Don't know if it's right solution but it's working.

                /** @var Photo $photo */
                foreach ($entity->getPhotos() as $photo){
                    $photo->setEntity($entity);
                    $em->persist($photo);
                }

Upvotes: 0

Related Questions