I need some help when select only discriminator column from doctrine 2 when run the DQL below
SELECT p.type FROM AppBundleEntityProduct p
type
is discriminator column in entity AppBundleEntityProduct
@ORMDiscriminatorColumn(name="type", type="smallint")`
@ORMDiscriminatorMap({
"0" = "AppBundleEntityProduct",
"1" = "AppBundleEntityProductSingleIssue",
"2" = "AppBundleEntityProductCountBasedIssue",
"3" = "AppBundleEntityProductTimeBasedIssue"
})
I know that type
is not a real property in entity, but is there anyway for me to do that?
Thanks in advance!
Updated
After 2 days for reading Doctrine codes, I decided to override SqlWalker and create new Hydrator by the snippets below
Override SqlWalker
<?php
namespace ...;
use DoctrineORMQuerySqlWalker;
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;
}
}
Custom Hydrator
<?php
namespace ...;
use DoctrineORMInternalHydrationArrayHydrator;
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;
}
}
Configure custom hydrator
orm:
...
hydrators:
CustomHydrator: YourNamespaceToCustomHydrator
Final step
$query = $queryBuilder->getQuery();
$query->setHint(DoctrineORMQuery::HINT_CUSTOM_OUTPUT_WALKER, 'YourNamespaceToCustomSqlWalker');
$query->setHint(YourNamespaceToCustomSqlWalker::FORCE_GET_DISCRIMINATOR_COLUMN, array($rootAlias)); // this alias will be used in CustomSqlWalker class
$query->setHint(YourNamespaceToCustomSqlWalker::DISCRIMINATOR_CLASS_MAP, $this->getClassName()); // this full-qualify class name will be used in CustomHydrator class
$products = $query->getResult('CustomHydrator');
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!
See Question&Answers more detail:
os