基于Doctrine ORM实现多类型用户映射的问题求助
正确实现Doctrine JOINED继承多用户类型映射方案
你的问题核心是JOINED继承的XML配置细节没到位,导致子表没生成关联Users的外键。以下是标准的配置方案,严格按这个来就能生成你要的表结构:
1. 基类User的XML配置
基类要明确指定继承策略、鉴别器列和子类映射,同时定义所有公共属性:
<!-- src/Entity/User.orm.xml --> <doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> <entity name="App\Entity\User" table="users"> <!-- 基类主键 --> <id name="id" type="integer" column="id"> <generator strategy="AUTO"/> </id> <!-- 继承配置 --> <inheritance-type>JOINED</inheritance-type> <discriminator-column name="discr" type="string" length="20"/> <discriminator-map> <discriminator-mapping value="child" class="App\Entity\Child"/> <discriminator-mapping value="guardian" class="App\Entity\Guardian"/> <discriminator-mapping value="teacher" class="App\Entity\Teacher"/> </discriminator-map> <!-- 公共属性 --> <field name="username" type="string" length="50" unique="true"/> <field name="firstname" type="string" length="50"/> <field name="lastname" type="string" length="50"/> </entity> </doctrine-mapping>
2. 子类Teacher的XML配置
子类必须继承User,并且主键要和基类的主键完全一致(用NONE生成策略,因为主键由基类维护),然后添加专属属性:
<!-- src/Entity/Teacher.orm.xml --> <doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> <entity name="App\Entity\Teacher" table="teachers"> <!-- 继承基类,主键复用基类的id,作为外键关联users表 --> <id name="id" type="integer" column="user_id"> <generator strategy="NONE"/> </id> <!-- 专属属性 --> <field name="email" type="string" length="100" unique="true"/> <field name="phone" type="string" length="20"/> </entity> </doctrine-mapping>
3. 子类Guardian的XML配置
和Teacher类似,同时配置与Child的多对多关系:
<!-- src/Entity/Guardian.orm.xml --> <doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> <entity name="App\Entity\Guardian" table="guardians"> <id name="id" type="integer" column="user_id"> <generator strategy="NONE"/> </id> <!-- 专属属性 --> <field name="email" type="string" length="100" unique="true"/> <field name="phone" type="string" length="20"/> <!-- 多对多关联Child --> <many-to-many target-entity="App\Entity\Child" inversed-by="guardians"> <join-table name="child_guardian"> <join-columns> <join-column name="guardian_id" referenced-column-name="user_id"/> </join-columns> <inverse-join-columns> <inverse-join-column name="child_id" referenced-column-name="user_id"/> </inverse-join-columns> </join-table> </many-to-many> </entity> </doctrine-mapping>
4. 子类Child的XML配置
配置多对多的反向关联:
<!-- src/Entity/Child.orm.xml --> <doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> <entity name="App\Entity\Child" table="children"> <id name="id" type="integer" column="user_id"> <generator strategy="NONE"/> </id> <!-- 多对多反向关联Guardian --> <many-to-many target-entity="App\Entity\Guardian" mapped-by="guardians"/> </entity> </doctrine-mapping>
关键注意事项
- 所有子类的主键必须设置
generator strategy="NONE",因为主键值由基类User生成,子表的主键同时作为关联users表的外键,这是JOINED继承的核心要求。 - 鉴别器列
discr会自动添加到users表,Doctrine通过这个字段区分不同用户类型。 - 执行
doctrine:schema:update --force生成表结构后,检查子表(children/guardians/teachers)的user_id字段,应该自动创建外键关联users表的id。 - 实体类中,子类只需继承User类,不需要额外添加
user_id属性,Doctrine会自动处理关联逻辑。
内容的提问来源于stack exchange,提问作者O'Niel
相关产品推荐
相关产品推荐

