Search code examples
symfonycontrollerdoctrinearraycollection

Symfony does not remove Element from ArrayCollection


i want to remove an role from the roles-ArrayCollection in the User Entity. User and Role have an M:N connection.

In my Controller:

  $em = $this->getDoctrine()->getManager();
  $user = $em->getRepository('UserBundle:User')->find($userId);
  $user->removeRole($roleID);
  $em->flush();

If I execute the controller, there are no error messages. But the Role is still assigned to the user.

User Entity

namespace Chris\UserBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
use Doctrine\Common\Collections\ArrayCollection;
/**
 * User
 *
 * @ORM\Table(name="usermanagement_users")
 * @ORM\Entity(repositoryClass="Chris\UserBundle\Entity\UserRepository")
 */
class User implements  UserInterface,\Serializable
{
    /**
     * @ORM\ManyToMany(targetEntity="Role", inversedBy="users")
     *
     */
    private $roles;

    public function __construct()
    {
        $this->roles = new ArrayCollection();
        $this->isActive = true;

    }

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

    public function setRoles($roles){
        $this->roles[] = $roles;
    }

    public function removeRole($role){
            unset($this->roles->toArray()[$role]);

    }

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

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

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

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

    /**
     * @ORM\Column(type="string", length=60)
     */
    private $vorname;

    /**
     * @ORM\Column(type="string", length=60)
     */
    private $nachname;


    /**
     * @ORM\Column(type="datetime", nullable=true)
     */
    private $letzterLogin;



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



    public function setId($id){
        $this->id = $id;
    }


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


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

    /**
     * @see \Serializable::serialize()
     */
    public function serialize()
    {
        return serialize(array(
            $this->id,
            $this->username,
            $this->password,
            // see section on salt below
            // $this->salt,
        ));
    }

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

Role Entity

<?php
/**
 * Created by PhpStorm.
 * User: christianschade
 * Date: 02.02.15
 * Time: 19:29
 */

namespace Chris\UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\Role\RoleInterface;
use Doctrine\Common\Collections\ArrayCollection;
/**
 * Role
 * @ORM\Entity(repositoryClass="Chris\UserBundle\Entity\RoleRepository")
 * @ORM\Table(name="usermanagement_roles")
 */

class Role implements RoleInterface {
    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;
    /**
     * @ORM\Column(name="role", type="string", length=20, unique=true)
     */
    private $role;

    public function getRole() {
        return $this->role;
    }

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

    /**
     * @return ArrayCollection
     */
    public function getUsers()
    {
        return $this->users;
    }

    /**
     * @param ArrayCollection $users
     */
    public function setUsers($users)
    {
        $this->users = $users;
    }


    public function setRoles($roles)
    {
        $this->role = $roles;

        // allows for chaining
        return $this;
    }
    /**
     * @inheritDoc
     */
    public function getId()
    {
        return $this->id;
    }
    /**
     * @ORM\ManyToMany(targetEntity = "Chris\UserBundle\Entity\Group", inversedBy = "groups")
     *
     * @var ArrayCollection $group
     */
    private $group;

    /**
     * @return ArrayCollection
     */
    public function getGroup()
    {
        return $this->group;
    }

    /**
     * @param ArrayCollection $group
     */
    public function setGroup($group)
    {
        $this->group = $group;
    }

}

Solution

  • You should use ArrayCollection::removeElement() to remove the role.

    public function removeRole($role)
    {
        $this->roles->removeElement($role);
    }
    

    On a side note, I feel your getRoles() implementation is unorthodox as it would be recommended to return the ArrayCollection as is and call toArray() if you need to once you have retrieved it.

    public function getRoles()
    {
        return $this->roles;
    }