Doctrine2 - 如何按鉴别器列排序? [英] Doctrine2 - How can I order by a discriminator column?

查看:14
本文介绍了Doctrine2 - 如何按鉴别器列排序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我应该如何在学说存储库查询中按鉴别器列进行排序?

How should I go about ordering by a discriminator column in a doctrine repository query?

我有一个非常直接的设置,我有不同类型的付款明细,它可以是信用卡 (CC) 或借记单 (DO).

I have a pretty straight forward setup, I have different types of payment details, it can either be Credit Card (CC) or Debit Order (DO).

所以我实现了一个单表继承映射策略来实现这一点,但是当我尝试按鉴别器列进行排序时,问题就出现了,因为鉴别器列不存在于基类中.

So I've implemented a single table inheritance mapping strategy to achieve this, but the problem now comes in when I try to order by the discriminator column, since the discriminator column isn't present in the base class.

存储库功能:

public function getPaymentDetails (ClientContactInterface $clientContact)
{
    $dql = 'SELECT pd
            from
            AccountingBundle:PaymentDetail pd
            JOIN ClientProductBundle:ClientProduct cp
            WITH cp.payment_detail_id = pd.id
            WHERE
            cp.payment_detail_id = pd.id
            and cp.client_contact_id = :client_contact_id
            GROUP BY pd.id
            ORDER BY pd.method_type'; // Since pd.method_type is the discriminator column, I cannot order by it. And I need to be able to.

    $em = $this->getEntityManager();
    $query = $em->createQuery($dql)->setParameter('client_contact_id', $clientContact->getId());
    return $query->getResult();
}

基本 PaymentDetail 实体:

Base PaymentDetail entity:

/**
 * @ORMEntity(repositoryClass="AccountingBundleRepositoryPaymentDetailRepository")
 * @ORMInheritanceType("SINGLE_TABLE")
 * @ORMTable(name="PaymentDetails")
 * @ORMDiscriminatorColumn(name="PaymentMethodType", type="string")
 * @ORMDiscriminatorMap({ "DO" = "DOPaymentDetail", "CC" = "CCPaymentDetail"})
 */

class PaymentDetail implements PaymentDetailInterface
{

    /**
     * @var integer $id
     *
     * @ORMColumn(name="id", type="integer")
     * @ORMId
     * @ORMGeneratedValue(strategy="AUTO")
     */
    protected  $id;

    /* etc... */
}

Debit Order PaymentDetail 实体:

Debit Order PaymentDetail entity:

/**
 * AccountingBundleEntityDOPaymentDetail
 *
 * @ORMTable(name="PaymentDetails")
 * @ORMEntity
 */
class DOPaymentDetail extends PaymentDetail implements DOPaymentDetailInterface
{

    /**
     * @var string $account_holder
     *
     * @ORMColumn(name="DOAccountHolder", type="string", length=255)
     */
    protected $account_holder;

    /* etc... */
}

Credit Card PaymentDetail 实体:

Credit Card PaymentDetail entity:

/**
 * AccountingBundleEntityCCPaymentDetail
 *
 * @ORMTable(name="PaymentDetails")
 * @ORMEntity
 */
class CCPaymentDetail extends PaymentDetail implements CCPaymentDetailInterface
{

    /**
     *
     * @var string $card_holder
     *
     * @ORMColumn(name="CCCardHolder", type="string", length=255)
     */
    protected $card_holder;

    /* etc... */
}

当我尝试这样做时,出现此错误,

When I try that, I get this error,

Error: Class AccountingBundleEntityPaymentDetail has no field or association named method_type") 

推荐答案

尽管 TYPE 尚未实现到学说的核心,但仍然可以将其实现为自定义用户函数.

Even though TYPE is not implemented yet into the core of doctrine it's still possible to implement it as a custom user function.

有人已经完成了一项了不起的工作,为我们实施.以防万一该资源将来会被删除,这里是 php7+ 的一个稍微调整的版本:

Someone already did an amazing job and implemented it for us. Just in case the resource will be removed in the future, here is a slightly adjusted version for php7+:

<?php
use DoctrineORMMappingClassMetadataInfo;
use DoctrineORMQueryASTFunctionsFunctionNode;
use DoctrineORMQueryLexer;
use DoctrineORMQueryParser;
use DoctrineORMQueryQueryException;
use DoctrineORMQuerySqlWalker;

class TypeFunction extends FunctionNode
{
    /**
     * @var string
     */
    public $dqlAlias;

    public function getSql(SqlWalker $sqlWalker): string
    {
        /** @var ClassMetadataInfo $class */
        $class = $sqlWalker->getQueryComponent($this->dqlAlias)['metadata'];
        $tableAlias = $sqlWalker->getSQLTableAlias($class->getTableName(), $this->dqlAlias);

        if (!isset($class->discriminatorColumn['name'])) {
            $message = 'TYPE() only supports entities with a discriminator column.';
            throw QueryException::semanticalError($message);
        }

        return $tableAlias . '.' . $class->discriminatorColumn['name'];
    }

    public function parse(Parser $parser)
    {
        $parser->match(Lexer::T_IDENTIFIER);
        $parser->match(Lexer::T_OPEN_PARENTHESIS);
        $this->dqlAlias = $parser->IdentificationVariable();
        $parser->match(Lexer::T_CLOSE_PARENTHESIS);
    }
}

现在您可以通过执行以下操作按鉴别器列排序:

Now you can order by the discriminator column by doing something like:

SELECT e, TYPE(e) AS HIDDEN my_type FROM Entity e ORDER BY my_type DESC;

这篇关于Doctrine2 - 如何按鉴别器列排序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆