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

如何从Doctrine仓库获取鉴别器类型?单表继承场景查询问题

Fixing Discriminator Field Selection in Doctrine Single Table Inheritance Queries

I’ve run into this exact issue with Doctrine’s single table inheritance (STI) before. The problem arises because Doctrine manages the discriminator field internally by default—it’s not mapped as a regular property on your entity, so trying to select it directly in DQL throws an error. Here are the most reliable ways to solve this:

1. Map the Discriminator as a Read-Only Property

The cleanest approach is to explicitly map the discriminator field to a read-only property on your base Flux entity. This lets you safely select it in queries or access it via a getter method.

Update your base Flux entity like this:

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\FluxRepository")
 * @ORM\InheritanceType("SINGLE_TABLE")
 * @ORM\DiscriminatorColumn(name="type", type="string")
 * @ORM\DiscriminatorMap({
 *     "flux_type_a" = FluxTypeA::class,
 *     "flux_type_b" = FluxTypeB::class
 * })
 */
abstract class Flux
{
    // ... your existing entity properties and methods

    /**
     * @ORM\Column(name="type", type="string", readOnly=true)
     * Note: The name must match the @DiscriminatorColumn name exactly
     */
    private string $type;

    public function getType(): string
    {
        return $this->type;
    }
}

Key notes here:

  • The @Column name must match the name value in @DiscriminatorColumn (in your case, "type").
  • Setting readOnly=true is critical—it tells Doctrine not to attempt to update this field, since it’s strictly managed by the STI mapping.

Once you’ve added this, you can include f.type in your repository queries without issues:

// In FluxRepository
public function getAllFluxWithType(): array
{
    return $this->createQueryBuilder('f')
        ->select('f', 'f.type')
        ->getQuery()
        ->getResult();
}

2. Use INSTANCE OF for Type Checks (If Filtering is Your Goal)

If you don’t need to select the type string but just want to filter or check the object’s concrete type, use Doctrine’s INSTANCE OF operator in DQL, or PHP’s native instanceof after fetching entities.

Example DQL Filter:

SELECT f FROM App\Entity\Flux f WHERE f INSTANCE OF App\Entity\FluxTypeA

Example PHP Type Check:

$allFlux = $this->getDoctrine()->getRepository(Flux::class)->findAll();

foreach ($allFlux as $flux) {
    if ($flux instanceof FluxTypeA) {
        // Handle type A logic
    } elseif ($flux instanceof FluxTypeB) {
        // Handle type B logic
    }
}

3. Native SQL Query (If You Can’t Modify the Entity)

If modifying the entity isn’t an option, you can use a native SQL query to fetch the discriminator field along with your entity data. Here’s a quick example:

// In FluxRepository
public function getAllFluxWithTypeNative(): array
{
    $conn = $this->getEntityManager()->getConnection();
    $sql = 'SELECT * FROM flux'; // Replace with your actual table name

    $resultSet = $conn->executeQuery($sql);
    return $resultSet->fetchAllAssociative();
}

Keep in mind this returns raw arrays instead of Doctrine entities, so use this only as a last resort.

Common Pitfalls to Avoid

  • Mismatched Column Names: Ensure the name in @Column matches exactly what’s in @DiscriminatorColumn—case sensitivity matters depending on your database.
  • Forgetting readOnly=true: Without this, Doctrine will try to persist changes to the discriminator field, leading to errors since it’s managed by STI.
  • Overusing Native Queries: Mapping the read-only property is almost always better than falling back to native SQL, as it keeps your code consistent with Doctrine’s entity management.

内容的提问来源于stack exchange,提问作者Liora Haydont

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 06:53:09