如何使用Doctrine创建自关联表的外键
Doctrine单表自关联外键未生成问题解决
我正在学习Doctrine,尝试在单表内通过外键建立两列的关联关系,以下是我的Entity类:
#[ORM\Entity(repositoryClass: BranchRepository::class)] #[ORM\Table(name: "tst_branches")] class Branch { #[ORM\Id] #[ORM\GeneratedValue(strategy: 'AUTO')] #[ORM\Column(type: 'integer')] private int $id; #[ORM\Column(type: 'integer')] #[ORM\ManyToOne( targetEntity: Branch::class, inversedBy: 'id' )] private int $parent_id; }
随后我通过以下命令创建数据库结构:
bin/console doctrine:schema:create
结果生成了预期的两列,但未创建连接parent_id与id列的外键。

请问需要修改哪些内容才能在数据库结构中生成外键?
预期效果如下:
问题原因与修改方案
你的代码存在两个核心问题:
- 关联注解与字段类型不匹配:
$parent_id字段被定义为int类型,但Doctrine的关联字段应对应关联对象(而非原始ID值),且#[ORM\Column]注解不能与关联注解混用——关联字段的列定义由Doctrine自动处理。 inversedBy参数错误:inversedBy需指向当前实体中对应反向关联的属性名,而非主键id。自关联的ManyToOne需要搭配对应的OneToMany反向关联。
修改后的实体类代码
#[ORM\Entity(repositoryClass: BranchRepository::class)] #[ORM\Table(name: "tst_branches")] class Branch { #[ORM\Id] #[ORM\GeneratedValue(strategy: 'AUTO')] #[ORM\Column(type: 'integer')] private int $id; // 移除#[ORM\Column]注解,字段类型改为关联对象Branch|null #[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')] // 显式指定外键列名,确保与预期一致 #[ORM\JoinColumn(name: 'parent_id', referencedColumnName: 'id', nullable: true)] private ?Branch $parent = null; // 添加反向OneToMany关联,用于关联当前分支的子分支 #[ORM\OneToMany(mappedBy: 'parent', targetEntity: self::class)] private Collection $children; // 构造函数初始化Collection对象 public function __construct() { $this->children = new ArrayCollection(); } // 可选:添加必要的 getter/setter 方法 public function getId(): int { return $this->id; } public function getParent(): ?Branch { return $this->parent; } public function setParent(?Branch $parent): self { $this->parent = $parent; return $this; } public function getChildren(): Collection { return $this->children; } }
执行数据库结构更新
修改完成后,重新生成数据库结构:
# 若为新表,直接重新创建 bin/console doctrine:schema:drop --force bin/console doctrine:schema:create # 若已有数据,使用更新命令 # bin/console doctrine:schema:update --force
关键说明
- 关联字段必须定义为实体对象类型(如
?Branch),而非原始ID类型,Doctrine会自动处理ID的存储与映射逻辑。 #[ORM\JoinColumn]可显式指定外键列名、是否允许为空等属性,确保生成的外键完全符合预期。- 反向关联
OneToMany虽非生成外键的强制要求,但能保证Doctrine实体关联操作的完整性,建议添加。
内容的提问来源于stack exchange,提问作者lubart
相关产品推荐
相关产品推荐

