Question

I have following entities with many to many relation: User

 /**
  * @ORM\ManyToMany(targetEntity = "Role", mappedBy = "users")
  *
  * @var ArrayCollection $roles;
  */
 private $roles;

Role

 /**
  * @ORM\ManyToMany(targetEntity = "User", inversedBy = "roles")
  * 
  * @var ArrayCollection $users
  */
 protected $users;

Doctrine generated 3 tables: user role user_role

Then I added data fixture:

class FixtureLoader implements FixtureInterface {
     public function load(ObjectManager $manager) {

          $role = new Role();
          $role->setName('Администратор');
          $role->setRole('ROLE_ADMIN');

          $manager->persist($role);

          $user = new User();
          $user->setUsername('ahmed');
          $user->setEmail('ahmed@umahanov.com');
          $user->setSalt(md5(time()));
          $user->setIsActive(false);

          $encoder = new MessageDigestPasswordEncoder('sha512',true,10);
          $password = $encoder->encodePassword('admin', $user->getSalt());
          $user->setPassword($password);
          //$user->getUserRoles()->add($role);
          $user->addRole($role);
          $manager->persist($user);

          $manager->flush();  

     }
}

When I load it using console, only 2 tables populated with data, but user_role table, which keep manytomany relations is empty.

How to solve this? Or I need to populate it myself?

/**
 * Umahanov\UserBundle\Entity\User
 *
 * @ORM\Entity
 * @ORM\Table(name="user")
 */
class User implements UserInterface, \Serializable {

     /**
      * @var integer
      *
      * @ORM\Column(name="id", type="integer")
      * @ORM\Id
      * @ORM\GeneratedValue(strategy="AUTO")
      */
     private $id;

     /**
      * @ORM\ManyToMany(targetEntity = "Role", mappedBy = "users")
      * @ORM\JoinTable(name="user_role",
      *   joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
      *   inverseJoinColumns={@ORM\JoinColumn(name="role_id", referencedColumnName="id")}
      *   )
      * @var ArrayCollection $roles;
      */
     private $roles;

     /**
      * @var string
      *
      * @ORM\Column(name="username", type="string", length=25, unique=true)
      */
     private $username;

     /**
      * @var string
      *
      * @ORM\Column(name="salt", type="string", length=32)
      */
     private $salt;

     /**
      * @var string
      *
      * @ORM\Column(name="password", type="string", length=88)
      */
     private $password;

     /**
      * @var string
      *
      * @ORM\Column(name="email", type="string", length=60, unique=true)
      */
     private $email;

     /**
      * @var boolean
      *
      * @ORM\Column(name="is_active", type="boolean")
      */
     private $isActive;

     public function __construct() {
          $this->isActive = false;
          $this->salt = md5(uniqid(null, true));
          $this->roles = new ArrayCollection();
     }

     /**
      * Get roles (array)
      *
      * @return array
      */
     public function getRoles() {
          return $this->roles->toArray();
     }

     /**
      * @inheritDoc
      */
     public function eraseCredentials() {

     }

     /**
      * @see \Serializable::serialize()
      */
     public function serialize() {
          return serialize(array(
                      $this->id,
                  ));
     }

     /**
      * @see \Serializable::unserialize()
      */
     public function unserialize($serialized) {
          list (
                  $this->id,
                  ) = unserialize($serialized);
     }

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

     /**
      * Set username
      *
      * @param  string $username
      * @return User
      */
     public function setUsername($username) {
          $this->username = $username;

          return $this;
     }

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

     /**
      * Set salt
      *
      * @param  string $salt
      * @return User
      */
     public function setSalt($salt) {
          $this->salt = $salt;

          return $this;
     }

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

     /**
      * Set password
      *
      * @param  string $password
      * @return User
      */
     public function setPassword($password) {
          $this->password = $password;

          return $this;
     }

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

     /**
      * Set email
      *
      * @param  string $email
      * @return User
      */
     public function setEmail($email) {
          $this->email = $email;

          return $this;
     }

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

     /**
      * Set is_active
      *
      * @param  boolean $isActive
      * @return User
      */
     public function setIsActive($isActive) {
          $this->isActive = $isActive;

          return $this;
     }

     /**
      * Get is_active
      *
      * @return boolean
      */
     public function getIsActive() {
          return $this->isActive;
     }

     /**
      * Сравнивает пользователя с другим пользователем и определяет
      * один и тот же ли это человек.
      * 
      * @param UserInterface $user The user
      * @return boolean True if equal, false othwerwise.
      */
     public function equals(UserInterface $user) {
          return md5($this->getUsername()) == md5($user->getUsername());
     }

     /**
      * Add roles
      *
      * @param \Umahanov\UserBundle\Entity\Role $roles
      * @return User
      */
     public function addRole(\Umahanov\UserBundle\Entity\Role $roles) {
          $this->roles[] = $roles;

          return $this;
     }

     /**
      * Remove roles
      *
      * @param \Umahanov\UserBundle\Entity\Role $roles
      */
     public function removeRole(\Umahanov\UserBundle\Entity\Role $roles) {
          $this->roles->removeElement($roles);
     }

}

And here is role:

/**
 * @ORM\Entity
 * @ORM\Table(name="role")
 */
class Role implements RoleInterface {

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

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

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

     /**
      * @ORM\Column(type="datetime", name="created_at")
      *
      * @var DateTime $createdAt;
      */
     protected $createdAt;

     public function getRole() {

          return $this->role;
     }

     /**
      * @ORM\ManyToMany(targetEntity = "User", inversedBy = "roles")
      * 
      * @var ArrayCollection $users
      */
     protected $users;


     public function getCreatedAt() {
          return $this->createdAt;
     }

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


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

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

        return $this;
    }

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

    /**
     * Set role
     *
     * @param string $role
     * @return Role
     */
    public function setRole($role)
    {
        $this->role = $role;

        return $this;
    }

    /**
     * Set createdAt
     *
     * @param \DateTime $createdAt
     * @return Role
     */
    public function setCreatedAt($createdAt)
    {
        $this->createdAt = $createdAt;

        return $this;
    }

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

        return $this;
    }

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

    /**
     * Get users
     *
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getUsers()
    {
        return $this->users;
    }
}
Was it helpful?

Solution

When you set related entities, they must be set on the both sides: For User class:

 /**
  * Add roles
  *
  * @param \Umahanov\UserBundle\Entity\Role $roles
  * @return User
  */
 public function addRole(\Umahanov\UserBundle\Entity\Role $roles) {
      $this->roles[] = $roles;
      $roles->addUser($this);

      return $this;
 }

OTHER TIPS

I do it in a slightly different way and it works for me.
I have one file for the Role (called Groups in my case) as follow:

<?php

class LoadGroupsData extends AbstractFixture implements OrderedFixtureInterface
{
    public function load(ObjectManager $manager)
    {
        foreach($this->container->getParameter('my_groups') as $key => $value)
        {
            $group = new Groups();
            $group->setRole($key);
            $group->setName($value);

            $manager->persist($group);
            $manager->flush();

            $this->addReference($key, $group);
        }
    }

    public function getOrder()
    {
        return 1;
    }
}

And one file for the Users as follow:

<?php

class LoadUsersData extends AbstractFixture implements OrderedFixtureInterface
{

    public function load(ObjectManager $manager)
    {
        foreach($this->container->getParameter('my_users') as $key => $value)
        {
            $user = new Users();
            $user->setUsername($key);

            $encoder = $this->container->get('security.encoder_factory')->getEncoder($user);
            $user->setPassword($encoder->encodePassword($value, $user->getSalt()));

            $user->addRole($this->getReference('ROLE_ADMIN'));

            $manager->persist($user);
        }
        $manager->flush();
    }

    public function getOrder()
    {
        return 2;
    }
}

My fixtures are proceed in order: the Groups are persisted and flushed and the object stored in an object shared between the fixture. The Users are then created and attached to the Groups stored in the shared object.

So the main difference with you is that my Groups objects (Role in your case) are persisted and flushed before trying to set them to the user.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top