virtualLast
virtualLast

Reputation: 593

Trying to understand Symfony ManyToMany error

im trying to get my head around symfony and doctrine, I am trying to create a Many to Many relationship between User + Group. I am using "symfony/maker-bundle": "^1.13", which allows me to generate the entities via the command line. I generated a User entity which looks like this:

/**
 * @ApiResource(
 *     normalizationContext={"groups"={"user:read"}},
 *     denormalizationContext={"groups"={"user:write"}},
 * )
 * @ORM\Entity(repositoryClass="App\Repository\UserRepository")
 */
class User implements UserInterface
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=180, unique=true)
     * @Groups({"user:read", "user:write"})
     */
    private $email;

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

    /**
     * @var string The hashed password
     * @ORM\Column(type="string")
     * @Groups({"user:write"})
     */
    private $password;

    /**
     * @ORM\Column(type="string", length=255)
     * @Groups({"user:read"})
     */
    private $uuid;

    /**
     * @ORM\ManyToMany(targetEntity="App\Entity\Group", inversedBy="users")
     * @Groups({"user:read", "user:write"})
     */
    private $groups;

    public function __construct()
    {
        $this->uuid = Uuid:: uuid4()->toString();
        $this->groups = new ArrayCollection();
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getEmail(): ?string
    {
        return $this->email;
    }

    public function setEmail(string $email): self
    {
        $this->email = $email;

        return $this;
    }

    /**
     * A visual identifier that represents this user.
     *
     * @see UserInterface
     */
    public function getUsername(): string
    {
        return (string) $this->email;
    }

    /**
     * @see UserInterface
     */
    public function getRoles(): array
    {
        $roles = $this->roles;
        // guarantee every user at least has ROLE_USER
        $roles[] = 'ROLE_USER';

        return array_unique($roles);
    }

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

        return $this;
    }

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

    public function setPassword(string $password): self
    {
        $this->password = $password;

        return $this;
    }

    /**
     * @see UserInterface
     */
    public function getSalt()
    {
        // not needed when using the "bcrypt" algorithm in security.yaml
    }

    /**
     * @see UserInterface
     */
    public function eraseCredentials()
    {
        // If you store any temporary, sensitive data on the user, clear it here
        // $this->plainPassword = null;
    }

    public function getUuid(): ?string
    {
        return $this->uuid;
    }

    public function setUuid(string $uuid): self
    {
        $this->uuid = $uuid;

        return $this;
    }

    /**
     * @return Collection|Group[]
     */
    public function getGroups(): Collection
    {
        return $this->groups;
    }

    public function addGroup(Group $group): self
    {
        if (!$this->groups->contains($group)) {
            $this->groups[] = $group;
        }

        return $this;
    }

    public function removeGroup(Group $group): self
    {
        if ($this->groups->contains($group)) {
            $this->groups->removeElement($group);
        }

        return $this;
    }
}

I also have generated the Group Entity which you can see below:

/**
 * @ApiResource()
 * @ORM\Entity(repositoryClass="App\Repository\GroupRepository")
 */
class Group
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

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

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

    /**
     * @ORM\ManyToMany(targetEntity="App\Entity\User", mappedBy="groups")
     */
    private $users;

    public function __construct()
    {
        $this->uuid = Uuid::uuid4()->toString();
        $this->users = new ArrayCollection();
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getName(): ?string
    {
        return $this->name;
    }

    public function setName(string $name): self
    {
        $this->name = $name;

        return $this;
    }

    public function getUuid(): ?string
    {
        return $this->uuid;
    }

    public function setUuid(string $uuid): self
    {
        $this->uuid = $uuid;

        return $this;
    }

    /**
     * @return Collection|User[]
     */
    public function getUsers(): Collection
    {
        return $this->users;
    }

    public function addUser(User $user): self
    {
        if (!$this->users->contains($user)) {
            $this->users[] = $user;
            $user->addGroup($this);
        }

        return $this;
    }

    public function removeUser(User $user): self
    {
        if ($this->users->contains($user)) {
            $this->users->removeElement($user);
            $user->removeGroup($this);
        }

        return $this;
    }
}

I am trying to use the ApiPlatform as well to autogenerate end points for me to create users, groups etc. Now when I try and create a new user I get the following error.

An exception occurred while executing 'SELECT t0.id AS id_1, t0.name AS name_2, t0.uuid AS uuid_3 FROM group t0 INNER JOIN user_group ON t0.id = user_group.group_id WHERE user_group.user_id = ?' with params [6]:

SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'group t0 INNER JOIN user_group ON t0.id = user_group.group_id WHERE user_group.u' at line 1

What I want to know is: 1) Why am i getting this error? 2) How can i fix it?

checking my database I can see that the user record gets created. My initial thought is that when ApiPlatform tries to return the newly created user object it is trying to find the associated group data, but why does it fail and 500 error instead of just giving me a blank array or something? There are 0 groups in the database at this time, is that what is causing my error?

Upvotes: 0

Views: 158

Answers (2)

weaverryan
weaverryan

Reputation: 530

It may be that group is a reserved word in Maria (I believe it is).

Add an @ORM\Table(name="groups") and try it again.

Cheers!

Upvotes: 2

sadikoff
sadikoff

Reputation: 111

I'm not sure but it looks like you are using MariaDB, have you configured doctrine for it?

doctrine:
    dbal:
        server_version: 'mariadb-10.2.12'  # set here your actual DB version

Probably it will fix your problem

Upvotes: 0

Related Questions