【问题标题】:How to get the discriminator type from repository如何从存储库中获取鉴别器类型
【发布时间】:2018-08-10 03:14:22
【问题描述】:

我目前在学说中为我的一个实体使用单表继承。标题如下所示:

/**
 * Flux
 *
 * @ORM\InheritanceType("SINGLE_TABLE")
 * @ORM\DiscriminatorColumn(name="type", type="string")
 * @ORM\DiscriminatorMap({"flux" = "Flux", "news" = "FluxNews", "mission" = "FluxMission", "offer" = "FluxOffer", "survey" = "FluxSurvey", "linkedin" = "FluxLinkedin", "facebook" = "FluxFacebook", "youtube" = "FluxYoutube", "twitter" = "FluxTwitter"})
 * @ORM\Entity(repositoryClass="AppBundle\Repository\FluxRepository")
 */
class Flux
{

    protected $type = "flux";

    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /* other fields */

}

我正在尝试在通量存储库中创建一个函数,该函数将从所有通量对象中获取数据。我要收集的重要数据之一是对象的类型(鉴别器字段),以了解它是什么类型的对象。

在我的存储库中,我的选择类似于:

$queryBuilder->select('f.id', 'f.type', 'f.createdAt', 'IDENTITY(f.createdBy) as CreatedBy','COUNT(DISTINCT c.id) as allClicks', 'COUNT(DISTINCT IDENTITY(c.clicker)) as clicks', 'f.postUrl')
            ->groupBy('f.id');

f 是flux。如果我删除 'f.type' 它可以正常工作,但我需要该数据。 如果我保留'f.type',我会收到以下错误:

[Semantical Error] line 0, col 15 near 'type, f.createdAt,': Error: Class AppBundle\Entity\Flux\Flux 没有名为 type 的字段或关联

我猜是因为类型是鉴别器字段,它不在普通字段中。有没有办法让我访问存储库中的数据?

我可以在我的控制器中访问,但我真的很想保持我的代码干净,并在存储库中对这些数据进行所有查询。 到目前为止我看到的唯一选择是创建另一个字段,juste保存相同的类型但它真的不干净,我想知道是否有一种方法可以使用学说来获取这个字段的值。

【问题讨论】:

    标签: php doctrine symfony-2.8


    【解决方案1】:

    根据docs,可以使用INSTANCE OF来实现。

    当您想使用鉴别器值时,使用 类元数据 并构造 CASE 表达式,您可以为每个实例选择值:

    $meta = $em->getMetadataFactory()->getMetadataFor(Flux::class);
    $discriminatorMap = $meta->discriminatorMap;
    $caseQl = '(case';
    foreach ($discriminatorMap as $fieldValue => $class) {
        $caseQl .= " when p INSTANCE OF " . $class . " then '" . $fieldValue . "'";
    }
    $caseQl .= ' else 0 end) as HIDDEN atype';
    $qb->addSelect($caseQl);
    $qb->having("atype LIKE :type");
    $qb->setParameter('type', '%FluxNew%');
    

    注意,字段atype被定义为HIDDEN,所以它不会在结果中返回。

    同样对于这个解决方案 have 需要使用,而不是 where(因为 atype 是一个计算值)。

    或者,您可以使用 Doctrine\ORM\Query::HINT_INCLUDE_META_COLUMNS 在结果中包含外键列值:

    $paginator->getQuery()
    ->setHint(\Doctrine\ORM\Query::HINT_INCLUDE_META_COLUMNS, true)
    ->setHydrationMode(\Doctrine\ORM\Query::HYDRATE_ARRAY);
    

    参考资料:

    【讨论】:

      【解决方案2】:

      请参阅this question。但是我觉得这种方式实在是太复杂了。

      如果我是你,我会覆盖你的查询。变成这样:

      $queryBuilder->select(f, COUNT(DISTINCT c.id) as allClicks, COUNT(DISTINCT IDENTITY(c.clicker)) as clicks)->from(Flux f)->groupBy(f.id);

      你会得到不同的结果,见docs

      所以,从f 获取您需要的类型。

      我希望你明白了。

      【讨论】:

      • 谢谢,但我看不出您的查询对我正在尝试做的事情有什么帮助,我希望最终能够搜索该类型,所以我仍然需要访问存储库中的“f.type”。我查看了链接,它看起来像我的问题,但答案对我没有帮助。我想这是不可能的
      • @LioraHaydont 我的回答解决了问题中的查询。如果要在 Where 子句中使用类型,请在查询中使用 INSTANCE OF 运算符
      • 我不能在查询中将 INSTANCE OF 与 LIKE 一起使用。就像我说的那样,在我的控制器中获得 Flux 对象后,我已经有了访问类型的方法,但我希望能够对其进行查询。
      • 如你所愿。如果您必须在查询中使用 LIKE => 例如,您可以使用 FROM FluxNews 和 FluxFacebook 将查询更改为 UNION
      猜你喜欢
      • 1970-01-01
      • 2019-03-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-27
      • 2022-01-16
      • 1970-01-01
      • 2022-01-16
      相关资源
      最近更新 更多