Symfony4 FOSRestBundle 尝试保留 ManyToMany SQL 语法错误
Symfony4 FOSRestBundle try to persist ManyToMany SQL syntax error
我收到 SQL 语法错误:
An exception occurred while executing 'INSERT INTO group (name) VALUES (?)' with params [\"Entwickler\"]:\n\nSQLSTATE[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 (name) VALUES ('Entwickler')' at line 1
当我尝试保留具有多对多关系的实体时。
场景
我有一个名为 folder
的实体和一个名为 group
的实体。这些实体之间是多对多的关系,因为一个组可以有多个文件夹,一个文件夹可以有多个组。
已有 1 个文件夹 ID 为 1
。现在我想创建一个组,想把id为1的文件夹加入这个组
组实体
<?php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* @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\ManyToMany(targetEntity="App\Entity\Folder", inversedBy="groups")
* @ORM\JoinTable(
* name="group_folder",
* joinColumns={
* @ORM\JoinColumn(name="group_id", referencedColumnName="id")
* },
* inverseJoinColumns={
* @ORM\JoinColumn(name="folder_id", referencedColumnName="id")
* }
* )
*/
private $folder;
public function __construct()
{
$this->folder = new ArrayCollection();
}
public function getId()
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
/**
* @return Collection|Folder[]
*/
public function getFolder(): Collection
{
return $this->folder;
}
public function addFolder(Folder $folder): self
{
if (!$this->folder->contains($folder)) {
$this->folder[] = $folder;
}
return $this;
}
public function removeFolder(Folder $folder): self
{
if ($this->folder->contains($folder)) {
$this->folder->removeElement($folder);
}
return $this;
}
}
文件夹实体
<?php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Entity(repositoryClass="App\Repository\FolderRepository")
*/
class Folder
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @var string
*
* @ORM\Column(type="string", length=45)
* @Assert\NotBlank()
*/
private $name;
/**
* @var Secret[]
* @ORM\OneToMany(targetEntity="App\Entity\Secret", mappedBy="folder")
*/
private $secrets;
/**
* @var Folder[]
*
* @ORM\OneToMany(targetEntity="Folder", mappedBy="parent")
*/
private $children;
/**
* @var Folder
*
* @ORM\ManyToOne(targetEntity="Folder", inversedBy="children")
* @ORM\JoinColumn(name="parent", referencedColumnName="id")
*/
private $parent;
/**
* @ORM\ManyToMany(targetEntity="App\Entity\Group", mappedBy="folder")
*/
private $groups;
public function __construct()
{
$this->children = new ArrayCollection();
$this->secrets = new ArrayCollection();
$this->groups = new ArrayCollection();
}
public function getId()
{
return $this->id;
}
/**
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* @param string $name
*/
public function setName($name)
{
$this->name = $name;
}
/**
* @return Secret[]|ArrayCollection
*/
public function getSecrets()
{
return $this->secrets;
}
/**
* @return Folder[]|ArrayCollection
*/
public function getChildren()
{
return $this->children;
}
/**
* @param Folder $children
*/
public function addChildren($children)
{
$this->children[] = $children;
$children->setParent($this);
}
/**
* @return Folder
*/
public function getParent()
{
return $this->parent;
}
/**
* @param Folder $parent
*/
public function setParent($parent)
{
$this->parent = $parent;
}
/**
* @return Collection|Group[]
*/
public function getGroups(): Collection
{
return $this->groups;
}
public function addGroup(Group $group): self
{
if (!$this->groups->contains($group)) {
$this->groups[] = $group;
$group->addFolder($this);
}
return $this;
}
public function removeGroup(Group $group): self
{
if ($this->groups->contains($group)) {
$this->groups->removeElement($group);
$group->removeFolder($this);
}
return $this;
}
}
GroupType 形式
<?php
namespace App\Form;
use App\Entity\Folder;
use App\Entity\Group;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class GroupType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('folder', EntityType::class, [
'class' => Folder::class,
'multiple' => true
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Group::class,
]);
}
}
我将 POST 请求发送到
的控制器操作
/**
* @param Request $request
* @return View
*
* @Rest\Post("/api/groups", name="api_group_create")
*/
public function CreateGroupAction(Request $request)
{
$group = new Group();
$form = $this->createForm(GroupType::class, $group);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($group);
$em->flush();
return View::create($group, 201);
}
return View::create($form, 400);
}
我发给的请求正文/api/groups
{
"group": {
"name": "Entwickler",
"folder": [
1
]
}
}
我尝试了很多不同的方法来解决这个问题,但没有任何效果像我预期的那样。这让我抓狂了好几个小时。
感谢 Mathieu Dormeval,这就是解决方案。
我更改了组实体定义:
/**
* @ORM\Entity(repositoryClass="App\Repository\GroupRepository")
*/
class Group
收件人:
/**
* @ORM\Entity(repositoryClass="App\Repository\GroupRepository")
* @ORM\Table(name="groups")
*/
class Group
我收到 SQL 语法错误:
An exception occurred while executing 'INSERT INTO group (name) VALUES (?)' with params [\"Entwickler\"]:\n\nSQLSTATE[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 (name) VALUES ('Entwickler')' at line 1
当我尝试保留具有多对多关系的实体时。
场景
我有一个名为 folder
的实体和一个名为 group
的实体。这些实体之间是多对多的关系,因为一个组可以有多个文件夹,一个文件夹可以有多个组。
已有 1 个文件夹 ID 为 1
。现在我想创建一个组,想把id为1的文件夹加入这个组
组实体
<?php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* @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\ManyToMany(targetEntity="App\Entity\Folder", inversedBy="groups")
* @ORM\JoinTable(
* name="group_folder",
* joinColumns={
* @ORM\JoinColumn(name="group_id", referencedColumnName="id")
* },
* inverseJoinColumns={
* @ORM\JoinColumn(name="folder_id", referencedColumnName="id")
* }
* )
*/
private $folder;
public function __construct()
{
$this->folder = new ArrayCollection();
}
public function getId()
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
/**
* @return Collection|Folder[]
*/
public function getFolder(): Collection
{
return $this->folder;
}
public function addFolder(Folder $folder): self
{
if (!$this->folder->contains($folder)) {
$this->folder[] = $folder;
}
return $this;
}
public function removeFolder(Folder $folder): self
{
if ($this->folder->contains($folder)) {
$this->folder->removeElement($folder);
}
return $this;
}
}
文件夹实体
<?php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Entity(repositoryClass="App\Repository\FolderRepository")
*/
class Folder
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @var string
*
* @ORM\Column(type="string", length=45)
* @Assert\NotBlank()
*/
private $name;
/**
* @var Secret[]
* @ORM\OneToMany(targetEntity="App\Entity\Secret", mappedBy="folder")
*/
private $secrets;
/**
* @var Folder[]
*
* @ORM\OneToMany(targetEntity="Folder", mappedBy="parent")
*/
private $children;
/**
* @var Folder
*
* @ORM\ManyToOne(targetEntity="Folder", inversedBy="children")
* @ORM\JoinColumn(name="parent", referencedColumnName="id")
*/
private $parent;
/**
* @ORM\ManyToMany(targetEntity="App\Entity\Group", mappedBy="folder")
*/
private $groups;
public function __construct()
{
$this->children = new ArrayCollection();
$this->secrets = new ArrayCollection();
$this->groups = new ArrayCollection();
}
public function getId()
{
return $this->id;
}
/**
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* @param string $name
*/
public function setName($name)
{
$this->name = $name;
}
/**
* @return Secret[]|ArrayCollection
*/
public function getSecrets()
{
return $this->secrets;
}
/**
* @return Folder[]|ArrayCollection
*/
public function getChildren()
{
return $this->children;
}
/**
* @param Folder $children
*/
public function addChildren($children)
{
$this->children[] = $children;
$children->setParent($this);
}
/**
* @return Folder
*/
public function getParent()
{
return $this->parent;
}
/**
* @param Folder $parent
*/
public function setParent($parent)
{
$this->parent = $parent;
}
/**
* @return Collection|Group[]
*/
public function getGroups(): Collection
{
return $this->groups;
}
public function addGroup(Group $group): self
{
if (!$this->groups->contains($group)) {
$this->groups[] = $group;
$group->addFolder($this);
}
return $this;
}
public function removeGroup(Group $group): self
{
if ($this->groups->contains($group)) {
$this->groups->removeElement($group);
$group->removeFolder($this);
}
return $this;
}
}
GroupType 形式
<?php
namespace App\Form;
use App\Entity\Folder;
use App\Entity\Group;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class GroupType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('folder', EntityType::class, [
'class' => Folder::class,
'multiple' => true
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Group::class,
]);
}
}
我将 POST 请求发送到
的控制器操作/**
* @param Request $request
* @return View
*
* @Rest\Post("/api/groups", name="api_group_create")
*/
public function CreateGroupAction(Request $request)
{
$group = new Group();
$form = $this->createForm(GroupType::class, $group);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($group);
$em->flush();
return View::create($group, 201);
}
return View::create($form, 400);
}
我发给的请求正文/api/groups
{
"group": {
"name": "Entwickler",
"folder": [
1
]
}
}
我尝试了很多不同的方法来解决这个问题,但没有任何效果像我预期的那样。这让我抓狂了好几个小时。
感谢 Mathieu Dormeval,这就是解决方案。
我更改了组实体定义:
/**
* @ORM\Entity(repositoryClass="App\Repository\GroupRepository")
*/
class Group
收件人:
/**
* @ORM\Entity(repositoryClass="App\Repository\GroupRepository")
* @ORM\Table(name="groups")
*/
class Group