我有三个实体,我们称它们为Site
、Category
和Tag
。在此场景中,Category
和 Tag
具有从 Site
实体生成的复合 ID 和不唯一的外部 ID(site
和 id
一起是唯一的)。 Category
与 Tag
之间存在多对多关系。 (尽管我的问题也可以通过 ManyToOne 关系重现。)
Site
实体:
/**
* @ORM\Entity
*/
class Site
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string")
*/
private $name;
}
类别
实体:
/**
* @ORM\Entity
*/
class Category extends AbstractSiteAwareEntity
{
/**
* @ORM\Column(type="string")
*/
private $name;
/**
* @ORM\ManyToMany(targetEntity="Tag")
*/
private $tags;
}
Tag
实体:
/**
* @ORM\Entity
*/
class Tag extends AbstractSiteAwareEntity
{
/**
* @ORM\Column(type="string")
*/
private $name;
}
最后两个实体继承自 AbstractSiteAwareEntity
类,该类定义了复合索引:
abstract class AbstractSiteAwareEntity
{
/**
* @ORM\Id
* @ORM\ManyToOne(targetEntity="Site")
*/
public $site;
/**
* @ORM\Id
* @ORM\Column(type="integer")
*/
public $id;
}
作为 ManyToOne 关系的示例,让我们想象一个 Post
实体,它具有自动增量 ID 和对 Category
的引用:
/**
* @ORM\Entity
*/
class Post
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
public $id;
/**
* @ORM\ManyToOne(targetEntity="Category")
*/
private $category;
/**
* @ORM\Column(type="string")
*/
private $title;
/**
* @ORM\Column(type="string")
*/
private $content;
}
使用 bin/consoledoctrine:schema:update --dump-sql --force --complete
更新架构时,出现以下异常:
An exception occurred while executing 'ALTER TABLE category_tag ADD CONSTRAINT FK_D80F351812469DE2 FOREIGN KEY (category_id) REFERENCES Category (id) ON DELETE CASCADE':
SQLSTATE[HY000]: General error: 1005 Can't create table
xxxxxxx
.#sql-3cf_14b6
(errno: 150 "Foreign key constraint is incorrectly formed")
我不确定可能出了什么问题……我的实体定义是否有错误?或者这是一个 Doctrine 错误?
注意:我在 Symfony 3.4 上使用doctrine/dbal 2.6.3。
最佳答案
您必须在注释中定义连接列才能使其正常工作:
对于多对一关系:
/**
* @ORM\ManyToOne(targetEntity="Tag")
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="tag_site_id", referencedColumnName="site_id"),
* @ORM\JoinColumn(name="tag_id", referencedColumnName="id")
* })
**/
protected $tag;
对于多对多关系:
/**
* @ORM\ManyToMany(targetEntity="Tag")
* @ORM\JoinTable(name="category_tags",
* joinColumns={
* @ORM\JoinColumn(name="category_site_id", referencedColumnName="site_id"),
* @ORM\JoinColumn(name="category_id", referencedColumnName="id")
* },
* inverseJoinColumns={
* @ORM\JoinColumn(name="tag_site_id", referencedColumnName="site_id"),
* @ORM\JoinColumn(name="tag_id", referencedColumnName="id")
* }
* )
**/
protected $tags;
工作原理:创建 2 列作为外键,引用复合外键。
注意:在“@ORM\JoinColumn”设置中:
“referencedColumnName”设置是相关表上的 id 列名称,因此它应该已经存在。
“name”是存储外键并要创建的列名称,在ManyToOne的情况下,它不应与实体的任何列冲突。
joinColumns 定义的顺序很重要。复合外键应以在引用表中具有索引的列开头。在这种情况下,“@ORM\JoinColumn”到“site_id”应该是第一个。 Reference
关于php - Doctrine :具有复合键的实体之间的 ManyToX 关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49383754/