Question

Here is my TagAdmin class

protected function configureFormFields(FormMapper $formMapper) 
    { 
        $formMapper 
            ->add('name') 
            ->add('description') 
            ->add('slug','text',array( 
                'read_only' => true, 
            )) 
            ->add('categories', 'sonata_type_model', array('expanded' 
=> true, 'multiple' => true)); 
    } 

There is a manyToMany mapping between Categories and Tags.

I recently upgraded to Sonata Admin version 2.0.

I am sure it was working earlier, but now when I add new Categories to a Tag, I get a success flash message, but the change is not reflected.

The only other change I had made was to integrate the Chosen JQuery plugin for handling checkboxes. I have tried with removing that too, but it functions just the same.

What could be going wrong?

Here is the Tag class.

class Tag 
{ 
    /** 
     * @var integer $id 
     * 
     * @ORM\Column(name="id", type="integer") 
     * @ORM\Id 
     * @ORM\GeneratedValue(strategy="AUTO") 
     */ 
    private $id; 
    /** 
     * @var string $name 
     * 
     * @Gedmo\Sluggable(slugField="slug") 
     * @ORM\Column(name="name", type="string", length=255) 
     * @Gedmo\Translatable 
     */ 
    private $name; 
    /** 
     * @var text $description 
     * 
     * @ORM\Column(name="description", type="text") 
     * @Gedmo\Translatable 
     */ 
    private $description; 
    /** 
     * @ORM\ManyToMany(targetEntity="Category", mappedBy="tags") 
     */ 
    protected $categories; 
    /** 
     * @var string $slug 
     * @Gedmo\Slug(updatable=false) 
     * @ORM\Column(name="slug", type="string", length=255) 
     */ 
    private $slug; 
    public function __construct() 
    { 
        $this->categories = new \Doctrine\Common\Collections 
\ArrayCollection(); 
    } 
Was it helpful?

Solution

Sorry, this had nothing to do with Sonata.

It was a problem with the mapping. The Doctrine2 documentation states:

The owning side of a relationship determines the updates to the relationship in the database.

To fully understand this, remember how bidirectional associations are maintained in the object world. There are 2 references on each side of the association and these 2 references both represent the same association but can change independently of one another. Of course, in a correct application the semantics of the bidirectional association are properly maintained by the application developer (that’s his responsibility). Doctrine needs to know which of these two in-memory references is the one that should be persisted and which not. This is what the owning/inverse concept is mainly used for.

Changes made only to the inverse side of an association are ignored. Make sure to update both sides of a bidirectional association (or at least the owning side, from Doctrine’s point of view)

The owning side of a bidirectional association is the side Doctrine “looks at” when determining the state of the association, and consequently whether there is anything to do to update the association in the database.

My mapping was defined like this:-

class Tag
{
...
   /**
     * @ORM\ManyToMany(targetEntity="Category", mappedBy="tags")
     */
    protected $categories;
...
}

class Category
{
...
   /**
     * @ORM\ManyToMany(targetEntity="Tag", inversedBy="categories")
     */
    protected $tags;
...
}

Setting the "inversedBy" to Tag class, solved the issue. So the correct implementation is this:

class Tag
{
...
   /**
     * @ORM\ManyToMany(targetEntity="Category", inversedBy="tags")
     */
    protected $categories;
...
}

class Category
{
...
   /**
     * @ORM\ManyToMany(targetEntity="Tag", mappedBy="categories")
     */
    protected $tags;
...
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top