Search code examples
jsonsymfonydoctrine-ormdoctrinesymfony4

Symfony 4 - update JSON user roles


I have entity User with field roles:

/**
 * @ORM\Column(name="roles", type="json")
 */
private $roles = [];

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

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

    return $this;
}

I want to add functionality to update user role from ROLE_ADMIN to ROLE_USER. I tried this in my controller but instead of replacing ROLE_ADMIN with ROLE_USER it inerts this: "ROLE_ADMIN""ROLE_USER". This is my controller:

public function updateuser(Request $request, $id) {
    $entityManager = $this->getDoctrine()->getManager();
    $usr = $this->getDoctrine()->getRepository(User::class)->find($id);
    $usr->setRoles("ROLE_USER");
    $entityManager->persist($usr);
    $entityManager->flush();

Solution

    1. First of all its best practice that every users has at least a default role like ROLE_USER. If you want to give users extra roles then you add them with beside ROLE_USER, like for example ROLE_ADMIN.

    2. Now take a close look how arrays work in PHP. Let's take the code of you setter function setRoles.

    When you write the value assignment like this $this->roles[] = $roles, then a value is added to the array . Thats why you in you code you have both roles inside you array now. The already existing ROLE_ADMIN and after the function call you added ROLE_USER.

    When you write the value assignment like this $this->roles = $roles, then the whole array is overwritten with the new value.

    Conclusion:

    Thats how you code should look like if you want a simple solution:

       public function setRoles(array $roles): self
       {
        $this->roles = $roles;
    
        return $this;
       }
    

    Then you can call it like this:

    $user->setRoles(['ROLE_USER']);