You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 20:23:10