0

I'm trying to create a ManyToMany relationship between Sonata's User and an entity called "Network" that resides in my bundle.

The idea is to be able to assign multiple Networks to each user via the User creation/edition of SonataAdmin.

Here's what I've got:

User Entity:

<?php
namespace Application\Sonata\UserBundle\Entity;

use Sonata\UserBundle\Entity\BaseUser as BaseUser;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;

class User extends BaseUser
{
    /**
     * @var integer $id
     */
    protected $id;

    /**
     * @ORM\ManyToMany(targetEntity="\Acme\TestBundle\Entity\Network", mappedBy="users", cascade={"persist", "remove"})
     */
    protected $networks;

    public function __construct()
    {
        parent::__construct();
        $this->networks = new ArrayCollection();
    }

    /**
     * Get id
     *
     * @return integer $id
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Add network
     *
     * @param \Acme\TestBundle\Entity\Network $network
     * @return User
     */
    public function addNetwork($network)
    {
        $this->networks[] = $network;

        $network->addUser($this);

        return $this;
    }

    /**
     * Remove network
     *
     * @param \Acme\TestBundle\Entity\Network $network
     */
    public function removeNetwork($network)
    {
        $this->networks->removeElement($network);

        $network->removeUser($this);
    }

    /**
     * Get networks
     *
     * @return \Doctrine\Common\Collections\ArrayCollection
     */
    public function getNetworks()
    {
        return $this->networks;
    }
}

Network Entity:

<?php
namespace Acme\TestBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;

/**
* @ORM\Entity
*/
class Network
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="string", length=255)
     */
    protected $name;

    /**
     * @ORM\ManyToMany(targetEntity="\Application\Sonata\UserBundle\Entity\User", inversedBy="networks")
     * @ORM\JoinTable(name="Networks_Users")
     */
    protected $users;

    public function __construct()
    {
        $this->users = new ArrayCollection();
    }

    public function __toString()
    {
        return $this->getName();
    }

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set name
     *
     * @param string $name
     * @return Network
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

    /**
     * Get name
     *
     * @return string 
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Add user
     *
     * @param \Application\Sonata\UserBundle\Entity\User $user
     * @return Network
     */
    public function addUser($user)
    {
        $this->users[] = $user;

        return $this;
    }

    /**
     * Remove user
     *
     * @param \Application\Sonata\UserBundle\Entity\User $user
     */
    public function removeUser($user)
    {
        $this->users->removeElement($user);
    }

    /**
     * Get users
     *
     * @return \Doctrine\Common\Collections\ArrayCollection
     */
    public function getUsers()
    {
        return $this->users;
    }
}

app\config.yml

sonata_user:
    admin:
        user:
            class: Acme\TestBundle\Admin\UserAdmin
    #...#

User Admin class:

<?php
namespace Acme\TestBundle\Admin;

use Sonata\UserBundle\Admin\Model\UserAdmin as SonataUserAdmin;

class UserAdmin extends SonataUserAdmin
{
    /**
     * {@inheritdoc}
     */
    protected function configureFormFields(\Sonata\AdminBundle\Form\FormMapper $formMapper)
    {
        parent::configureFormFields($formMapper);

        $formMapper
            ->with('Networks')
            ->add('networks', 'sonata_type_model', array(
                'by_reference' => false,
                'required' => false,
                'expanded' => false,
                'multiple' => true,
                'label' => 'Choose the user Networks',
                'class' => 'AcmeTestBundle:Network'
            ))
            ->end();
    }
}

Here's the problem:

When I edit an existing User via SonataAdmin and assign certain Networks to it changes are persisted to the database but the selector appears empty, as if no Networks were ever assigned. If I try to assign Networks again, I get a database constraint violation message (as it would be expected).

I discovered that for some reason the $networks ArrayCollection is returning NULL, as if the relationship could not be established from the User side:

$usr = $this->getUser();
$selected_networks = $usr->getNetworks(); // returns NULL

If I attempt to manage Users from the Network side, everything works fine (with no additions or changes to the actual code):

<?php
namespace Acme\TestBundle\Admin;

use Sonata\AdminBundle\Form\FormMapper;

class NetworkAdmin extends Admin
{
    /**
     * @param \Sonata\AdminBundle\Form\FormMapper $formMapper
     *
     * @return void
     */
    protected function configureFormFields(FormMapper $formMapper)
    {
        $formMapper
            ->with('General')
            ->add('name')
            ->end()
            ->with('Users')
            ->add('users', 'sonata_type_model', array(
                'by_reference' => false,
                'required' => false,
                'expanded' => false,
                'multiple' => true,
                'label' => 'Choose the network Users',
                'class' => 'ApplicationSonataUserBundle:User'
            ))              
        ;
    }
}

I'm stumped. Any ideas?

Thank you all.

Edward
  • 311
  • 2
  • 11
  • **Update - Profiler is showing the following message for Doctrine:** `Acme\TestBundle\Entity\Network: The association Acme\TestBundle\Entity\Network#users refers to the inverse side field Application\Sonata\UserBundle\Entity\User#networks which does not exist.` – Edward Aug 24 '14 at 22:02
  • 1
    **I found the solution!** You just have to edit the file `Application/Sonata/UserBundle/Resources/config/doctrine/User.orm.xml` and add the relationship column in XML format: `` – Edward Aug 26 '14 at 02:24

0 Answers0