/** * Dump the contents of the identity map into a stream. * * @param EntityManager $em * @return void */ public function dumpIdentityMap(EntityManager $em) { $uow = $em->getUnitOfWork(); $identityMap = $uow->getIdentityMap(); $fh = fopen($this->file, "x+"); if (count($identityMap) == 0) { fwrite($fh, "Flush Operation [" . $this->context . "] - Empty identity map.\n"); return; } fwrite($fh, "Flush Operation [" . $this->context . "] - Dumping identity map:\n"); foreach ($identityMap as $className => $map) { fwrite($fh, "Class: " . $className . "\n"); foreach ($map as $idHash => $entity) { fwrite($fh, " Entity: " . $this->getIdString($entity, $uow) . " " . spl_object_hash($entity) . "\n"); fwrite($fh, " Associations:\n"); $cm = $em->getClassMetadata($className); foreach ($cm->associationMappings as $field => $assoc) { fwrite($fh, " " . $field . " "); $value = $cm->reflFields[$field]->getValue($entity); if ($assoc['type'] & ClassMetadata::TO_ONE) { if ($value === null) { fwrite($fh, " NULL\n"); } else { if ($value instanceof Proxy && !$value->__isInitialized__) { fwrite($fh, "[PROXY] "); } fwrite($fh, $this->getIdString($value, $uow) . " " . spl_object_hash($value) . "\n"); } } else { $initialized = !$value instanceof PersistentCollection || $value->isInitialized(); if ($value === null) { fwrite($fh, " NULL\n"); } else { if ($initialized) { fwrite($fh, "[INITIALIZED] " . $this->getType($value) . " " . count($value) . " elements\n"); foreach ($value as $obj) { fwrite($fh, " " . $this->getIdString($obj, $uow) . " " . spl_object_hash($obj) . "\n"); } } else { fwrite($fh, "[PROXY] " . $this->getType($value) . " unknown element size\n"); foreach ($value->unwrap() as $obj) { fwrite($fh, " " . $this->getIdString($obj, $uow) . " " . spl_object_hash($obj) . "\n"); } } } } } } } fclose($fh); }
/** * {@inheritdoc} * * @param object $sourceEntity the entity source of this association * @param object $targetEntity the entity to load data in * @param EntityManager $em * @param array $joinColumnValues Values of the join columns of $sourceEntity. */ public function load($sourceEntity, $targetEntity, $em, array $joinColumnValues = array()) { $targetClass = $em->getClassMetadata($this->targetEntityName); if ($this->isOwningSide) { $inverseField = isset($targetClass->inverseMappings[$this->sourceEntityName][$this->sourceFieldName]) ? $targetClass->inverseMappings[$this->sourceEntityName][$this->sourceFieldName]->sourceFieldName : false; // Mark inverse side as fetched in the hints, otherwise the UoW would // try to load it in a separate query (remember: to-one inverse sides can not be lazy). $hints = array(); if ($inverseField) { $hints['fetched'][$targetClass->name][$inverseField] = true; if ($targetClass->subClasses) { foreach ($targetClass->subClasses as $targetSubclassName) { $hints['fetched'][$targetSubclassName][$inverseField] = true; } } } /* cascade read-only status if ($em->getUnitOfWork()->isReadOnly($sourceEntity)) { $hints[Query::HINT_READ_ONLY] = true; } */ $targetEntity = $em->getUnitOfWork()->getEntityPersister($this->targetEntityName)->load($joinColumnValues, $targetEntity, $this, $hints); if ($targetEntity !== null && $inverseField && !$targetClass->isCollectionValuedAssociation($inverseField)) { $targetClass->reflFields[$inverseField]->setValue($targetEntity, $sourceEntity); } } else { $conditions = array(); $sourceClass = $em->getClassMetadata($this->sourceEntityName); $owningAssoc = $targetClass->getAssociationMapping($this->mappedBy); // TRICKY: since the association is specular source and target are flipped foreach ($owningAssoc->targetToSourceKeyColumns as $sourceKeyColumn => $targetKeyColumn) { if (isset($sourceClass->fieldNames[$sourceKeyColumn])) { $conditions[$targetKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity); } else { throw MappingException::joinColumnMustPointToMappedField($sourceClass->name, $sourceKeyColumn); } } $targetEntity = $em->getUnitOfWork()->getEntityPersister($this->targetEntityName)->load($conditions, $targetEntity, $this); if ($targetEntity !== null) { $targetClass->setFieldValue($targetEntity, $this->mappedBy, $sourceEntity); } } return $targetEntity; }
/** * Finds a single entity by a set of criteria. * * @param string $column * @param string $value * @return object */ public function findOneBy(array $criteria) { return $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName)->load($criteria); }
/** * Walks down a SelectExpression AST node and generates the corresponding SQL. * * @param SelectExpression $selectExpression * @return string The SQL. */ public function walkSelectExpression($selectExpression) { $sql = ''; $expr = $selectExpression->expression; if ($expr instanceof AST\PathExpression) { if ($expr->type == AST\PathExpression::TYPE_STATE_FIELD) { $parts = $expr->parts; $fieldName = array_pop($parts); $dqlAlias = $expr->identificationVariable . (!empty($parts) ? '.' . implode('.', $parts) : ''); $qComp = $this->_queryComponents[$dqlAlias]; $class = $qComp['metadata']; if (!$selectExpression->fieldIdentificationVariable) { $resultAlias = $fieldName; } else { $resultAlias = $selectExpression->fieldIdentificationVariable; } if ($class->isInheritanceTypeJoined()) { $tableName = $this->_em->getUnitOfWork()->getEntityPersister($class->name)->getOwningTable($fieldName); } else { $tableName = $class->getTableName(); } $sqlTableAlias = $this->getSqlTableAlias($tableName, $dqlAlias); $columnName = $class->getQuotedColumnName($fieldName, $this->_platform); $columnAlias = $this->getSqlColumnAlias($columnName); $sql .= $sqlTableAlias . '.' . $columnName . ' AS ' . $columnAlias; $columnAlias = $this->_platform->getSQLResultCasing($columnAlias); $this->_rsm->addScalarResult($columnAlias, $resultAlias); } else { throw QueryException::invalidPathExpression($expr->type); } } else { if ($expr instanceof AST\AggregateExpression) { if (!$selectExpression->fieldIdentificationVariable) { $resultAlias = $this->_scalarResultCounter++; } else { $resultAlias = $selectExpression->fieldIdentificationVariable; } $columnAlias = 'sclr' . $this->_aliasCounter++; $sql .= $this->walkAggregateExpression($expr) . ' AS ' . $columnAlias; $this->_scalarResultAliasMap[$resultAlias] = $columnAlias; $columnAlias = $this->_platform->getSQLResultCasing($columnAlias); $this->_rsm->addScalarResult($columnAlias, $resultAlias); } else { if ($expr instanceof AST\Subselect) { if (!$selectExpression->fieldIdentificationVariable) { $resultAlias = $this->_scalarResultCounter++; } else { $resultAlias = $selectExpression->fieldIdentificationVariable; } $columnAlias = 'sclr' . $this->_aliasCounter++; $sql .= '(' . $this->walkSubselect($expr) . ') AS ' . $columnAlias; $this->_scalarResultAliasMap[$resultAlias] = $columnAlias; $columnAlias = $this->_platform->getSQLResultCasing($columnAlias); $this->_rsm->addScalarResult($columnAlias, $resultAlias); } else { if ($expr instanceof AST\Functions\FunctionNode) { if (!$selectExpression->fieldIdentificationVariable) { $resultAlias = $this->_scalarResultCounter++; } else { $resultAlias = $selectExpression->fieldIdentificationVariable; } $columnAlias = 'sclr' . $this->_aliasCounter++; $sql .= $this->walkFunction($expr) . ' AS ' . $columnAlias; $this->_scalarResultAliasMap[$resultAlias] = $columnAlias; $columnAlias = $this->_platform->getSQLResultCasing($columnAlias); $this->_rsm->addScalarResult($columnAlias, $resultAlias); } else { if ($expr instanceof AST\SimpleArithmeticExpression) { if (!$selectExpression->fieldIdentificationVariable) { $resultAlias = $this->_scalarResultCounter++; } else { $resultAlias = $selectExpression->fieldIdentificationVariable; } $columnAlias = 'sclr' . $this->_aliasCounter++; $sql .= $this->walkSimpleArithmeticExpression($expr) . ' AS ' . $columnAlias; $this->_scalarResultAliasMap[$resultAlias] = $columnAlias; $columnAlias = $this->_platform->getSQLResultCasing($columnAlias); $this->_rsm->addScalarResult($columnAlias, $resultAlias); } else { // IdentificationVariable or PartialObjectExpression if ($expr instanceof AST\PartialObjectExpression) { $dqlAlias = $expr->identificationVariable; $partialFieldSet = $expr->partialFieldSet; } else { $dqlAlias = $expr; $partialFieldSet = array(); } $queryComp = $this->_queryComponents[$dqlAlias]; $class = $queryComp['metadata']; if (!isset($this->_selectedClasses[$dqlAlias])) { $this->_selectedClasses[$dqlAlias] = $class; } $beginning = true; // Select all fields from the queried class foreach ($class->fieldMappings as $fieldName => $mapping) { if ($partialFieldSet && !in_array($fieldName, $partialFieldSet)) { continue; } if (isset($mapping['inherited'])) { $tableName = $this->_em->getClassMetadata($mapping['inherited'])->primaryTable['name']; } else { $tableName = $class->primaryTable['name']; } if ($beginning) { $beginning = false; } else { $sql .= ', '; } $sqlTableAlias = $this->getSqlTableAlias($tableName, $dqlAlias); $columnAlias = $this->getSqlColumnAlias($mapping['columnName']); $sql .= $sqlTableAlias . '.' . $class->getQuotedColumnName($fieldName, $this->_platform) . ' AS ' . $columnAlias; $columnAlias = $this->_platform->getSQLResultCasing($columnAlias); $this->_rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName, $class->name); } // Add any additional fields of subclasses (excluding inherited fields) // 1) on Single Table Inheritance: always, since its marginal overhead // 2) on Class Table Inheritance only if partial objects are disallowed, // since it requires outer joining subtables. if ($class->isInheritanceTypeSingleTable() || !$this->_query->getHint(Query::HINT_FORCE_PARTIAL_LOAD)) { foreach ($class->subClasses as $subClassName) { $subClass = $this->_em->getClassMetadata($subClassName); $sqlTableAlias = $this->getSqlTableAlias($subClass->primaryTable['name'], $dqlAlias); foreach ($subClass->fieldMappings as $fieldName => $mapping) { if (isset($mapping['inherited']) || $partialFieldSet && !in_array($fieldName, $partialFieldSet)) { continue; } if ($beginning) { $beginning = false; } else { $sql .= ', '; } $columnAlias = $this->getSqlColumnAlias($mapping['columnName']); $sql .= $sqlTableAlias . '.' . $subClass->getQuotedColumnName($fieldName, $this->_platform) . ' AS ' . $columnAlias; $columnAlias = $this->_platform->getSQLResultCasing($columnAlias); $this->_rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName, $subClassName); } // Add join columns (foreign keys) of the subclass //TODO: Probably better do this in walkSelectClause to honor the INCLUDE_META_COLUMNS hint foreach ($subClass->associationMappings as $fieldName => $assoc) { if ($assoc->isOwningSide && $assoc->isOneToOne() && !isset($subClass->inheritedAssociationFields[$fieldName])) { foreach ($assoc->targetToSourceKeyColumns as $srcColumn) { if ($beginning) { $beginning = false; } else { $sql .= ', '; } $columnAlias = $this->getSqlColumnAlias($srcColumn); $sql .= $sqlTableAlias . '.' . $srcColumn . ' AS ' . $columnAlias; $this->_rsm->addMetaResult($dqlAlias, $this->_platform->getSQLResultCasing($columnAlias), $srcColumn); } } } } } } } } } } return $sql; }
/** * Walks down a SelectExpression AST node and generates the corresponding SQL. * * @param SelectExpression $selectExpression * @return string The SQL. */ public function walkSelectExpression($selectExpression) { $sql = ''; $expr = $selectExpression->expression; $hidden = $selectExpression->hiddenAliasResultVariable; switch (true) { case $expr instanceof AST\PathExpression: if ($expr->type !== AST\PathExpression::TYPE_STATE_FIELD) { throw QueryException::invalidPathExpression($expr); } $fieldName = $expr->field; $dqlAlias = $expr->identificationVariable; $qComp = $this->queryComponents[$dqlAlias]; $class = $qComp['metadata']; $resultAlias = $selectExpression->fieldIdentificationVariable ?: $fieldName; $tableName = $class->isInheritanceTypeJoined() ? $this->em->getUnitOfWork()->getEntityPersister($class->name)->getOwningTable($fieldName) : $class->getTableName(); $sqlTableAlias = $this->getSQLTableAlias($tableName, $dqlAlias); $columnName = $this->quoteStrategy->getColumnName($fieldName, $class, $this->platform); $columnAlias = $this->getSQLColumnAlias($class->fieldMappings[$fieldName]['columnName']); $col = $sqlTableAlias . '.' . $columnName; $fieldType = $class->getTypeOfField($fieldName); if (isset($class->fieldMappings[$fieldName]['requireSQLConversion'])) { $type = Type::getType($fieldType); $col = $type->convertToPHPValueSQL($col, $this->conn->getDatabasePlatform()); } $sql .= $col . ' AS ' . $columnAlias; $this->scalarResultAliasMap[$resultAlias] = $columnAlias; if (!$hidden) { $this->rsm->addScalarResult($columnAlias, $resultAlias, $fieldType); $this->scalarFields[$dqlAlias][$fieldName] = $columnAlias; } break; case $expr instanceof AST\AggregateExpression: case $expr instanceof AST\Functions\FunctionNode: case $expr instanceof AST\SimpleArithmeticExpression: case $expr instanceof AST\ArithmeticTerm: case $expr instanceof AST\ArithmeticFactor: case $expr instanceof AST\Literal: case $expr instanceof AST\NullIfExpression: case $expr instanceof AST\CoalesceExpression: case $expr instanceof AST\GeneralCaseExpression: case $expr instanceof AST\SimpleCaseExpression: $columnAlias = $this->getSQLColumnAlias('sclr'); $resultAlias = $selectExpression->fieldIdentificationVariable ?: $this->scalarResultCounter++; $sql .= $expr->dispatch($this) . ' AS ' . $columnAlias; $this->scalarResultAliasMap[$resultAlias] = $columnAlias; if (!$hidden) { // We cannot resolve field type here; assume 'string'. $this->rsm->addScalarResult($columnAlias, $resultAlias, 'string'); } break; case $expr instanceof AST\Subselect: $columnAlias = $this->getSQLColumnAlias('sclr'); $resultAlias = $selectExpression->fieldIdentificationVariable ?: $this->scalarResultCounter++; $sql .= '(' . $this->walkSubselect($expr) . ') AS ' . $columnAlias; $this->scalarResultAliasMap[$resultAlias] = $columnAlias; if (!$hidden) { // We cannot resolve field type here; assume 'string'. $this->rsm->addScalarResult($columnAlias, $resultAlias, 'string'); } break; default: // IdentificationVariable or PartialObjectExpression if ($expr instanceof AST\PartialObjectExpression) { $dqlAlias = $expr->identificationVariable; $partialFieldSet = $expr->partialFieldSet; } else { $dqlAlias = $expr; $partialFieldSet = array(); } $queryComp = $this->queryComponents[$dqlAlias]; $class = $queryComp['metadata']; $resultAlias = $selectExpression->fieldIdentificationVariable ?: null; if (!isset($this->selectedClasses[$dqlAlias])) { $this->selectedClasses[$dqlAlias] = array('class' => $class, 'dqlAlias' => $dqlAlias, 'resultAlias' => $resultAlias); } $sqlParts = array(); // Select all fields from the queried class foreach ($class->fieldMappings as $fieldName => $mapping) { if ($partialFieldSet && !in_array($fieldName, $partialFieldSet)) { continue; } $tableName = isset($mapping['inherited']) ? $this->em->getClassMetadata($mapping['inherited'])->getTableName() : $class->getTableName(); $sqlTableAlias = $this->getSQLTableAlias($tableName, $dqlAlias); $columnAlias = $this->getSQLColumnAlias($mapping['columnName']); $quotedColumnName = $this->quoteStrategy->getColumnName($fieldName, $class, $this->platform); $col = $sqlTableAlias . '.' . $quotedColumnName; if (isset($class->fieldMappings[$fieldName]['requireSQLConversion'])) { $type = Type::getType($class->getTypeOfField($fieldName)); $col = $type->convertToPHPValueSQL($col, $this->platform); } $sqlParts[] = $col . ' AS ' . $columnAlias; $this->scalarResultAliasMap[$resultAlias][] = $columnAlias; $this->rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName, $class->name); } // Add any additional fields of subclasses (excluding inherited fields) // 1) on Single Table Inheritance: always, since its marginal overhead // 2) on Class Table Inheritance only if partial objects are disallowed, // since it requires outer joining subtables. if ($class->isInheritanceTypeSingleTable() || !$this->query->getHint(Query::HINT_FORCE_PARTIAL_LOAD)) { foreach ($class->subClasses as $subClassName) { $subClass = $this->em->getClassMetadata($subClassName); $sqlTableAlias = $this->getSQLTableAlias($subClass->getTableName(), $dqlAlias); foreach ($subClass->fieldMappings as $fieldName => $mapping) { if (isset($mapping['inherited']) || $partialFieldSet && !in_array($fieldName, $partialFieldSet)) { continue; } $columnAlias = $this->getSQLColumnAlias($mapping['columnName']); $quotedColumnName = $this->quoteStrategy->getColumnName($fieldName, $subClass, $this->platform); $col = $sqlTableAlias . '.' . $quotedColumnName; if (isset($subClass->fieldMappings[$fieldName]['requireSQLConversion'])) { $type = Type::getType($subClass->getTypeOfField($fieldName)); $col = $type->convertToPHPValueSQL($col, $this->platform); } $sqlParts[] = $col . ' AS ' . $columnAlias; $this->scalarResultAliasMap[$resultAlias][] = $columnAlias; $this->rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName, $subClassName); } } } $sql .= implode(', ', $sqlParts); } return $sql; }
/** * {@inheritdoc} * * @param object $sourceEntity the entity source of this association * @param object $targetEntity the entity to load data in * @param EntityManager $em * @param array $joinColumnValues Values of the join columns of $sourceEntity. * @todo Remove */ public function load($sourceEntity, $targetEntity, $em, array $joinColumnValues = array()) { return $em->getUnitOfWork()->getEntityPersister($this->targetEntityName)->loadOneToOneEntity($this, $sourceEntity, $targetEntity, $joinColumnValues); }
/** * {@inheritdoc} * * @param object $owningEntity * @param object $targetEntity * @param EntityManager $em */ public function load($owningEntity, $targetEntity, $em) { $sourceClass = $em->getClassMetadata($this->sourceEntityName); $targetClass = $em->getClassMetadata($this->targetEntityName); $conditions = array(); if ($this->isOwningSide) { foreach ($this->sourceToTargetKeyColumns as $sourceKeyColumn => $targetKeyColumn) { $conditions[$targetKeyColumn] = $sourceClass->getReflectionProperty($sourceClass->getFieldName($sourceKeyColumn))->getValue($owningEntity); } if ($targetClass->hasInverseAssociation($this->sourceFieldName)) { $targetClass->setFieldValue($targetEntity, $targetClass->inverseMappings[$this->_sourceFieldName]->getSourceFieldName(), $owningEntity); } } else { $owningAssoc = $em->getClassMetadata($this->targetEntityName)->getAssociationMapping($this->mappedByFieldName); foreach ($owningAssoc->getTargetToSourceKeyColumns() as $targetKeyColumn => $sourceKeyColumn) { $conditions[$sourceKeyColumn] = $sourceClass->getReflectionProperty($sourceClass->getFieldName($targetKeyColumn))->getValue($owningEntity); } $targetClass->setFieldValue($targetEntity, $this->mappedByFieldName, $owningEntity); } $em->getUnitOfWork()->getEntityPersister($this->targetEntityName)->load($conditions, $targetEntity); }