vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/SimpleObjectHydrator.php line 65

  1. <?php
  2. declare(strict_types=1);
  3. namespace Doctrine\ORM\Internal\Hydration;
  4. use Doctrine\ORM\Internal\SQLResultCasing;
  5. use Doctrine\ORM\Mapping\ClassMetadata;
  6. use Doctrine\ORM\Mapping\MappingException;
  7. use Doctrine\ORM\Query;
  8. use Exception;
  9. use RuntimeException;
  10. use ValueError;
  11. use function array_keys;
  12. use function array_search;
  13. use function count;
  14. use function in_array;
  15. use function key;
  16. use function reset;
  17. use function sprintf;
  18. class SimpleObjectHydrator extends AbstractHydrator
  19. {
  20.     use SQLResultCasing;
  21.     /** @var ClassMetadata */
  22.     private $class;
  23.     /**
  24.      * {@inheritDoc}
  25.      */
  26.     protected function prepare()
  27.     {
  28.         if (count($this->resultSetMapping()->aliasMap) !== 1) {
  29.             throw new RuntimeException('Cannot use SimpleObjectHydrator with a ResultSetMapping that contains more than one object result.');
  30.         }
  31.         if ($this->resultSetMapping()->scalarMappings) {
  32.             throw new RuntimeException('Cannot use SimpleObjectHydrator with a ResultSetMapping that contains scalar mappings.');
  33.         }
  34.         $this->class $this->getClassMetadata(reset($this->resultSetMapping()->aliasMap));
  35.     }
  36.     /**
  37.      * {@inheritDoc}
  38.      */
  39.     protected function cleanup()
  40.     {
  41.         parent::cleanup();
  42.         $this->_uow->triggerEagerLoads();
  43.         $this->_uow->hydrationComplete();
  44.     }
  45.     /**
  46.      * {@inheritDoc}
  47.      */
  48.     protected function hydrateAllData()
  49.     {
  50.         $result = [];
  51.         while ($row $this->statement()->fetchAssociative()) {
  52.             $this->hydrateRowData($row$result);
  53.         }
  54.         $this->_em->getUnitOfWork()->triggerEagerLoads();
  55.         return $result;
  56.     }
  57.     /**
  58.      * {@inheritDoc}
  59.      */
  60.     protected function hydrateRowData(array $row, array &$result)
  61.     {
  62.         $entityName       $this->class->name;
  63.         $data             = [];
  64.         $discrColumnValue null;
  65.         // We need to find the correct entity class name if we have inheritance in resultset
  66.         if ($this->class->inheritanceType !== ClassMetadata::INHERITANCE_TYPE_NONE) {
  67.             $discrColumn     $this->class->getDiscriminatorColumn();
  68.             $discrColumnName $this->getSQLResultCasing($this->_platform$discrColumn['name']);
  69.             // Find mapped discriminator column from the result set.
  70.             $metaMappingDiscrColumnName array_search($discrColumnName$this->resultSetMapping()->metaMappingstrue);
  71.             if ($metaMappingDiscrColumnName) {
  72.                 $discrColumnName $metaMappingDiscrColumnName;
  73.             }
  74.             if (! isset($row[$discrColumnName])) {
  75.                 throw HydrationException::missingDiscriminatorColumn(
  76.                     $entityName,
  77.                     $discrColumnName,
  78.                     key($this->resultSetMapping()->aliasMap)
  79.                 );
  80.             }
  81.             if ($row[$discrColumnName] === '') {
  82.                 throw HydrationException::emptyDiscriminatorValue(key(
  83.                     $this->resultSetMapping()->aliasMap
  84.                 ));
  85.             }
  86.             $discrMap $this->class->discriminatorMap;
  87.             if (! isset($discrMap[$row[$discrColumnName]])) {
  88.                 throw HydrationException::invalidDiscriminatorValue($row[$discrColumnName], array_keys($discrMap));
  89.             }
  90.             $entityName       $discrMap[$row[$discrColumnName]];
  91.             $discrColumnValue $row[$discrColumnName];
  92.             unset($row[$discrColumnName]);
  93.         }
  94.         foreach ($row as $column => $value) {
  95.             // An ObjectHydrator should be used instead of SimpleObjectHydrator
  96.             if (isset($this->resultSetMapping()->relationMap[$column])) {
  97.                 throw new Exception(sprintf('Unable to retrieve association information for column "%s"'$column));
  98.             }
  99.             $cacheKeyInfo $this->hydrateColumnInfo($column);
  100.             if (! $cacheKeyInfo) {
  101.                 continue;
  102.             }
  103.             // If we have inheritance in resultset, make sure the field belongs to the correct class
  104.             if (isset($cacheKeyInfo['discriminatorValues']) && ! in_array((string) $discrColumnValue$cacheKeyInfo['discriminatorValues'], true)) {
  105.                 continue;
  106.             }
  107.             // Check if value is null before conversion (because some types convert null to something else)
  108.             $valueIsNull $value === null;
  109.             // Convert field to a valid PHP value
  110.             if (isset($cacheKeyInfo['type'])) {
  111.                 $type  $cacheKeyInfo['type'];
  112.                 $value $type->convertToPHPValue($value$this->_platform);
  113.             }
  114.             if ($value !== null && isset($cacheKeyInfo['enumType'])) {
  115.                 $originalValue $value;
  116.                 try {
  117.                     $value $this->buildEnum($originalValue$cacheKeyInfo['enumType']);
  118.                 } catch (ValueError $e) {
  119.                     throw MappingException::invalidEnumValue(
  120.                         $entityName,
  121.                         $cacheKeyInfo['fieldName'],
  122.                         (string) $originalValue,
  123.                         $cacheKeyInfo['enumType'],
  124.                         $e
  125.                     );
  126.                 }
  127.             }
  128.             $fieldName $cacheKeyInfo['fieldName'];
  129.             // Prevent overwrite in case of inherit classes using same property name (See AbstractHydrator)
  130.             if (! isset($data[$fieldName]) || ! $valueIsNull) {
  131.                 $data[$fieldName] = $value;
  132.             }
  133.         }
  134.         if (isset($this->_hints[Query::HINT_REFRESH_ENTITY])) {
  135.             $this->registerManaged($this->class$this->_hints[Query::HINT_REFRESH_ENTITY], $data);
  136.         }
  137.         $uow    $this->_em->getUnitOfWork();
  138.         $entity $uow->createEntity($entityName$data$this->_hints);
  139.         $result[] = $entity;
  140.         if (isset($this->_hints[Query::HINT_INTERNAL_ITERATION]) && $this->_hints[Query::HINT_INTERNAL_ITERATION]) {
  141.             $this->_uow->hydrationComplete();
  142.         }
  143.     }
  144. }