如何在准则2中选择区分列 [英] How to select discriminator column in doctrine 2

查看:127
本文介绍了如何在准则2中选择区分列的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在运行下面的DQL时从准则2中仅选择区分列时,我需要一些帮助

I need some help when select only discriminator column from doctrine 2 when run the DQL below

SELECT p.type FROM AppBundle\Entity\Product p

type是实体AppBundle\Entity\Product

@ORM\DiscriminatorColumn(name="type", type="smallint")`

@ORM\DiscriminatorMap({
    "0" = "AppBundle\Entity\Product",
    "1" = "AppBundle\Entity\Product\SingleIssue",
    "2" = "AppBundle\Entity\Product\CountBasedIssue",
    "3" = "AppBundle\Entity\Product\TimeBasedIssue"
})

我知道type不是实体中的不动产,但是我仍然可以这样做吗?

I know that type is not a real property in entity, but is there anyway for me to do that?

提前谢谢!

在阅读了两天的代码后,我决定重写SqlWalker并通过下面的代码片段创建新的Hydrator

After 2 days for reading Doctrine codes, I decided to override SqlWalker and create new Hydrator by the snippets below

<?php

namespace ...;

use Doctrine\ORM\Query\SqlWalker;

class CustomSqlWalker extends SqlWalker
{
    const FORCE_GET_DISCRIMINATOR_COLUMN = 'forceGetDiscriminatorColumn';
    const DISCRIMINATOR_CLASS_MAP = 'discriminatorClassMap';

    /**
     * {@inheritdoc}
     */
    public function walkSelectClause($selectClause)
    {
        $sql = parent::walkSelectClause($selectClause);
        $forceGetDiscriminatorColumn = $this->getQuery()->getHint(self::FORCE_GET_DISCRIMINATOR_COLUMN);
        if (empty($forceGetDiscriminatorColumn)) {
            return $sql;
        }

        foreach ($this->getQueryComponents() as $key => $queryComponent) {
            if (!in_array($key, $forceGetDiscriminatorColumn)) {
                continue;
            }

            $metadata = $queryComponent['metadata'];
            $discriminatorColumn = $metadata->discriminatorColumn['name'];
            $tableName = $metadata->table['name'];
            $tableAlias = $this->getSQLTableAlias($tableName, $key);
            $discriminatorColumnAlias = $this->getSQLColumnAlias($discriminatorColumn);
            $sql .= ", $tableAlias.$discriminatorColumn AS $discriminatorColumnAlias";
        }

        return $sql;
    }
}

自定义保湿器

<?php

namespace ...;

use Doctrine\ORM\Internal\Hydration\ArrayHydrator;
use PDO;

class CustomHydrator extends ArrayHydrator
{
    /**
     * {@inheritdoc}
     */
    protected function hydrateAllData()
    {
        $result = array();

        $rootClassName = null;
        if (isset($this->_hints['forceGetDiscriminatorColumn']) &&
            isset($this->_hints['discriminatorClassMap'])) {
            $rootClassName = $this->_hints['discriminatorClassMap'];
        }

        while ($data = $this->_stmt->fetch(PDO::FETCH_ASSOC)) {
            foreach ($data as $key => $value) {
                if ($this->hydrateColumnInfo($key) != null ||
                    empty($rootClassName)) {
                    continue;
                }

                $metadata = $this->getClassMetadata($rootClassName);
                $discriminatorColumn = $metadata->discriminatorColumn;
                $fieldName = $discriminatorColumn['fieldName'];
                $type = $discriminatorColumn['type'];
                $this->_rsm->addScalarResult(
                    $key, $fieldName, $type
                );
            }
            $this->hydrateRowData($data, $result);
        }

        return $result;
    }
}

配置自定义水龙头

orm:
    ...
    hydrators:
        CustomHydrator: YourNamespace\To\CustomHydrator

最后一步

$query = $queryBuilder->getQuery();
$query->setHint(\Doctrine\ORM\Query::HINT_CUSTOM_OUTPUT_WALKER, 'YourNamespace\To\CustomSqlWalker');
$query->setHint(\YourNamespace\To\CustomSqlWalker::FORCE_GET_DISCRIMINATOR_COLUMN, array($rootAlias)); // this alias will be used in CustomSqlWalker class
$query->setHint(\YourNamespace\To\CustomSqlWalker::DISCRIMINATOR_CLASS_MAP, $this->getClassName()); // this full-qualify class name will be used in CustomHydrator class

$products = $query->getResult('CustomHydrator');

TL; DR

我知道这是一个非常复杂的解决方案(可能只是针对我的情况),所以我希望有人可以给我另一种简单的方法来解决此问题,非常感谢!

TL;DR

I know this is a very complicated solution (may be just for my scenario), so I hope someone could give me another simple way to fix that, thanks so much!

推荐答案

无法直接访问鉴别符"列.

There is no direct access to the discriminator column.

可能会查询特殊类型的实体. 由于无法直接访问鉴别符"列, 教义提供实例的构造.

It may happen that the entities of a special type should be queried. Because there is no direct access to the discriminator column, Doctrine provides the INSTANCE OF construct.

您可以使用INSTANCE OF DQL查询您的实体类型

You can query for the type of your entity using the INSTANCE OF DQL as described in the docs. As example:

$query = $em->createQuery("SELECT product FROM AppBundle\Entity\AbstractProduct product WHERE product  INSTANCE OF AppBundle\Entity\Product");
$products = $query->getResult();

希望这会有所帮助

这篇关于如何在准则2中选择区分列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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