Как выбрать колонку дискриминатора в доктрине 2

Мне нужна помощь при выборе только столбца дискриминатора из доктрины 2 при запуске DQL ниже

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 это не реальная собственность в юридическом лице, но есть ли для меня возможность это сделать?

Заранее спасибо!

После 2 дней чтения кодов Доктрины я решил переопределить SqlWalker и создать новый Hydrator, используя приведенные ниже фрагменты.

Переопределить SqlWalker

<?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

Я знаю, что это очень сложное решение (может быть, только для моего сценария), поэтому я надеюсь, что кто-то может дать мне еще один простой способ исправить это, большое спасибо!

6

Решение

Прямой доступ к столбцу дискриминатора отсутствует.

Может случиться так, что сущности специального типа должны быть запрошены.
Поскольку нет прямого доступа к столбцу дискриминатора,
Доктрина обеспечивает МОМЕНТ конструкции.

Вы можете запросить тип вашей сущности, используя INSTANCE OF DQL как описано в документации. Как пример:

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

Надеюсь это поможет

8

Другие решения

Я использую этот маленький «хак»

  1. Определите общий интерфейс для ваших сущностей (необязательно, но рекомендуется)
  2. Создать getType метод в этом интерфейсе
  3. Создать константу в сущности Дискриминатор
  4. Вернуть правильную константу внутри каждого различаемого объекта

Таким образом, вы можете получить «универсальную» сущность дискриминатора (Product в твоем случае) и позвони getType на него.

Конечно, если вас интересует фильтрация результатов, выполняемая непосредственно с помощью sql, это совсем не решение, и, боюсь, на данный момент нет доступных решений.
Если вы найдете что-то лучшее, пожалуйста, поделитесь с нами.

5

По вопросам рекламы [email protected]