Doctrine继承关联实现咨询:PHP类可行模型的Doctrine映射问题
嘿,这个方案完全可行的!Doctrine对这种基于抽象类的继承关联支持得很好,我来一步步给你捋清楚怎么实现:
第一步:配置抽象类
GlobalClass的继承映射 Doctrine提供三种继承映射策略,你可以根据业务需求选择:
- 单表继承(Single Table Inheritance):所有子类数据存在同一张表,用鉴别器列区分类型,性能最优,适合子类字段差异不大的场景
- 类表继承(Class Table Inheritance):父类表存公共字段,每个子类对应单独的表存特有字段,结构更清晰,适合子类差异较大的情况
- 映射超类(Mapped Superclass):超类不生成数据表,子类各自生成独立表,适合仅共享逻辑不共享关联的场景
这里以最常用的单表继承为例,给你写具体代码:
<?php use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity * @ORM\InheritanceType("SINGLE_TABLE") * @ORM\DiscriminatorColumn(name="type", type="string") * @ORM\DiscriminatorMap({ * "class1" = "Class1", * "class2" = "Class2" * }) */ abstract class GlobalClass { /** * @ORM\Id * @ORM\GeneratedValue * @ORM\Column(type="integer") */ protected $id; // 公共字段示例 /** * @ORM\Column(type="string") */ protected $commonField; // 公共逻辑方法 // ... }
然后是子类实现:
<?php use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity */ class Class1 extends GlobalClass { /** * @ORM\Column(type="integer") */ private $class1SpecificField; // Class1专属方法 // ... }
<?php use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity */ class Class2 extends GlobalClass { /** * @ORM\Column(type="text") */ private $class2SpecificField; // Class2专属方法 // ... }
第二步:配置
Main类与GlobalClass的关联 因为Main需要包含多个组件,所以用一对多关联即可,直接关联抽象类GlobalClass,Doctrine会自动识别所有子类实例:
<?php use Doctrine\ORM\Mapping as ORM; use Doctrine\Common\Collections\ArrayCollection; /** * @ORM\Entity */ class Main { /** * @ORM\Id * @ORM\GeneratedValue * @ORM\Column(type="integer") */ private $id; /** * @ORM\OneToMany(targetEntity="GlobalClass", mappedBy="main", cascade={"persist", "remove"}) */ private $components; public function __construct() { $this->components = new ArrayCollection(); } // 添加组件的方法 public function addComponent(GlobalClass $component): void { if (!$this->components->contains($component)) { $this->components->add($component); $component->setMain($this); // 记得在GlobalClass中添加关联的反向属性 } } // 移除组件的方法 public function removeComponent(GlobalClass $component): void { if ($this->components->removeElement($component)) { $component->setMain(null); } } // 获取组件集合 public function getComponents(): ArrayCollection { return $this->components; } }
最后别忘了在GlobalClass中添加关联的反向端:
// 在GlobalClass类中新增以下代码 /** * @ORM\ManyToOne(targetEntity="Main", inversedBy="components") */ protected $main; public function setMain(?Main $main): void { $this->main = $main; } public function getMain(): ?Main { return $this->main; }
关键注意点
- 如果选择类表继承,只需把
GlobalClass的继承类型注解改成@ORM\InheritanceType("JOINED")即可,其余代码基本一致 - 关联的
cascade选项可根据需求调整:比如{"persist"}会自动保存新增的组件,{"remove"}会在删除Main实例时自动删除关联的组件 - 查询时,你可以直接查询
GlobalClass获取所有子类实例;也可以通过鉴别器列筛选特定类型:$em->getRepository(GlobalClass::class)->findBy(['type' => 'class1'])
后续新增子类(比如Class3),只需要在DiscriminatorMap里新增一条映射规则,就能无缝集成到现有结构中,非常灵活。
内容的提问来源于stack exchange,提问作者NewRehtse
相关产品推荐
相关产品推荐

