Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hydrating enumType as array gives *string* instead of Enum #9622

Closed
janedbal opened this issue Apr 1, 2022 · 3 comments
Closed

Hydrating enumType as array gives *string* instead of Enum #9622

janedbal opened this issue Apr 1, 2022 · 3 comments
Labels

Comments

@janedbal
Copy link
Contributor

janedbal commented Apr 1, 2022

Bug Report

As discussed in original topic: #9588, but I see this as a bug as it behaves differently than any custom type. So migrating from enums used as custom types to this native form is impossible. Tested version: 2.11.2

Summary

$queryBuilder = $this->createQueryBuilder('f')
    ->select('f.id, f.suit')
    ->getQuery()
    ->getResult() // suit is string, not Suit enum
;

Current behavior

Column defined as enumType gets hydrated as string when array hydration occurs.

How to reproduce

Use entity as described and fetch from query builder as array.

Expected behavior

To be hydrated as enum.

@derrabus derrabus added the Bug label Apr 4, 2022
@michnovka
Copy link
Contributor

Ok, so given this some debugging and thought, this is a bit more difficult than it seemed. The reason why find()/findAll() methods hydrate the Enum type correctly is, that this is handled on the UoW level inside createEntity() through ClassMetadata::reflFields[]->setValue(). When using select of individual fields OR when using getArrayResult(), then hydration is done on individual fields and entity itself is not created.

@michnovka
Copy link
Contributor

michnovka commented Apr 12, 2022

@derrabus I think that the issue here is that AbstractHydrator::hydrateAll() gets $resultSetMapping with scalarMappings set to string for suit column. I dont think I can access the enumType of the column from there. What would be the proper way? Can we leverage some other "mapping", like fieldMapping?

@michnovka
Copy link
Contributor

So I see the $resultSetMapping is set inside SqlWalker here

$fieldMapping = $class->fieldMappings[$fieldName];
$columnName = $this->quoteStrategy->getColumnName($fieldName, $class, $this->platform);
$columnAlias = $this->getSQLColumnAlias($fieldMapping['columnName']);
$col = $sqlTableAlias . '.' . $columnName;
if (isset($fieldMapping['requireSQLConversion'])) {
$type = Type::getType($fieldMapping['type']);
$col = $type->convertToPHPValueSQL($col, $this->conn->getDatabasePlatform());
}
$sql .= $col . ' AS ' . $columnAlias;
$this->scalarResultAliasMap[$resultAlias] = $columnAlias;
if (! $hidden) {
$this->rsm->addScalarResult($columnAlias, $resultAlias, $fieldMapping['type']);
$this->scalarFields[$dqlAlias][$fieldName] = $columnAlias;
}

Now the question is - do we introduce enumMappings? like

if(!empty($fieldMapping['enumType'])) {
    $this->rsm->addEnumMapping($columnAlias, $fieldMapping['enumType']);
}

then when walking $resultSetMapping->scalarMapping check for $resultSetMapping->enumMappings and if present cast to enum.

Or do you have another idea? Can we leverage something already present in the resultSetMapping?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants