vendor/doctrine/orm/src/Persisters/Entity/SingleTablePersister.php line 45

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace Doctrine\ORM\Persisters\Entity;
  4. use Doctrine\Common\Collections\Criteria;
  5. use Doctrine\ORM\Internal\SQLResultCasing;
  6. use Doctrine\ORM\Mapping\ClassMetadata;
  7. use Doctrine\ORM\Utility\PersisterHelper;
  8. use function array_flip;
  9. use function array_intersect;
  10. use function array_map;
  11. use function array_unshift;
  12. use function implode;
  13. /**
  14.  * Persister for entities that participate in a hierarchy mapped with the
  15.  * SINGLE_TABLE strategy.
  16.  *
  17.  * @link https://martinfowler.com/eaaCatalog/singleTableInheritance.html
  18.  */
  19. class SingleTablePersister extends AbstractEntityInheritancePersister
  20. {
  21.     use SQLResultCasing;
  22.     /**
  23.      * {@inheritDoc}
  24.      */
  25.     protected function getDiscriminatorColumnTableName()
  26.     {
  27.         return $this->class->getTableName();
  28.     }
  29.     /**
  30.      * {@inheritDoc}
  31.      */
  32.     protected function getSelectColumnsSQL()
  33.     {
  34.         if ($this->currentPersisterContext->selectColumnListSql !== null) {
  35.             return $this->currentPersisterContext->selectColumnListSql;
  36.         }
  37.         $columnList[] = parent::getSelectColumnsSQL();
  38.         $rootClass  $this->em->getClassMetadata($this->class->rootEntityName);
  39.         $tableAlias $this->getSQLTableAlias($rootClass->name);
  40.         // Append discriminator column
  41.         $discrColumn     $this->class->getDiscriminatorColumn();
  42.         $discrColumnName $discrColumn['name'];
  43.         $discrColumnType $discrColumn['type'];
  44.         $columnList[] = $tableAlias '.' $discrColumnName;
  45.         $resultColumnName $this->getSQLResultCasing($this->platform$discrColumnName);
  46.         $this->currentPersisterContext->rsm->setDiscriminatorColumn('r'$resultColumnName);
  47.         $this->currentPersisterContext->rsm->addMetaResult('r'$resultColumnName$discrColumnNamefalse$discrColumnType);
  48.         // Append subclass columns
  49.         foreach ($this->class->subClasses as $subClassName) {
  50.             $subClass $this->em->getClassMetadata($subClassName);
  51.             // Regular columns
  52.             foreach ($subClass->fieldMappings as $fieldName => $mapping) {
  53.                 if (isset($mapping['inherited'])) {
  54.                     continue;
  55.                 }
  56.                 $columnList[] = $this->getSelectColumnSQL($fieldName$subClass);
  57.             }
  58.             // Foreign key columns
  59.             foreach ($subClass->associationMappings as $assoc) {
  60.                 if (! $assoc['isOwningSide'] || ! ($assoc['type'] & ClassMetadata::TO_ONE) || isset($assoc['inherited'])) {
  61.                     continue;
  62.                 }
  63.                 $targetClass $this->em->getClassMetadata($assoc['targetEntity']);
  64.                 foreach ($assoc['joinColumns'] as $joinColumn) {
  65.                     $columnList[] = $this->getSelectJoinColumnSQL(
  66.                         $tableAlias,
  67.                         $joinColumn['name'],
  68.                         $this->quoteStrategy->getJoinColumnName($joinColumn$subClass$this->platform),
  69.                         PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $targetClass$this->em)
  70.                     );
  71.                 }
  72.             }
  73.         }
  74.         $this->currentPersisterContext->selectColumnListSql implode(', '$columnList);
  75.         return $this->currentPersisterContext->selectColumnListSql;
  76.     }
  77.     /**
  78.      * {@inheritDoc}
  79.      */
  80.     protected function getInsertColumnList()
  81.     {
  82.         $columns parent::getInsertColumnList();
  83.         // Add discriminator column to the INSERT SQL
  84.         $columns[] = $this->class->getDiscriminatorColumn()['name'];
  85.         return $columns;
  86.     }
  87.     /**
  88.      * {@inheritDoc}
  89.      */
  90.     protected function getSQLTableAlias($className$assocName '')
  91.     {
  92.         return parent::getSQLTableAlias($this->class->rootEntityName$assocName);
  93.     }
  94.     /**
  95.      * {@inheritDoc}
  96.      */
  97.     protected function getSelectConditionSQL(array $criteria$assoc null)
  98.     {
  99.         $conditionSql parent::getSelectConditionSQL($criteria$assoc);
  100.         if ($conditionSql) {
  101.             $conditionSql .= ' AND ';
  102.         }
  103.         return $conditionSql $this->getSelectConditionDiscriminatorValueSQL();
  104.     }
  105.     /**
  106.      * {@inheritDoc}
  107.      */
  108.     protected function getSelectConditionCriteriaSQL(Criteria $criteria)
  109.     {
  110.         $conditionSql parent::getSelectConditionCriteriaSQL($criteria);
  111.         if ($conditionSql) {
  112.             $conditionSql .= ' AND ';
  113.         }
  114.         return $conditionSql $this->getSelectConditionDiscriminatorValueSQL();
  115.     }
  116.     /** @return string */
  117.     protected function getSelectConditionDiscriminatorValueSQL()
  118.     {
  119.         $values array_map(
  120.             [$this->conn'quote'],
  121.             array_flip(array_intersect($this->class->discriminatorMap$this->class->subClasses))
  122.         );
  123.         if ($this->class->discriminatorValue !== null) { // discriminators can be 0
  124.             array_unshift($values$this->conn->quote($this->class->discriminatorValue));
  125.         }
  126.         $discColumnName $this->class->getDiscriminatorColumn()['name'];
  127.         $values     implode(', '$values);
  128.         $tableAlias $this->getSQLTableAlias($this->class->name);
  129.         return $tableAlias '.' $discColumnName ' IN (' $values ')';
  130.     }
  131.     /**
  132.      * {@inheritDoc}
  133.      */
  134.     protected function generateFilterConditionSQL(ClassMetadata $targetEntity$targetTableAlias)
  135.     {
  136.         // Ensure that the filters are applied to the root entity of the inheritance tree
  137.         $targetEntity $this->em->getClassMetadata($targetEntity->rootEntityName);
  138.         // we don't care about the $targetTableAlias, in a STI there is only one table.
  139.         return parent::generateFilterConditionSQL($targetEntity$targetTableAlias);
  140.     }
  141. }