The returned value is always an array of identifier values. If the entity
has a composite identifier then the identifier values are in the same
order as the identifier field names as returned by ClassMetadata#getIdentifierFieldNames().
public getEntityIdentifier ( object $entity ) : array | ||
$entity | object | |
Résultat | array | The identifier values. |
/** * convert foreign identifiers into scalar foreign key values to avoid object to string conversion failures. * * @param ClassMetadata $class * @param array $id * * @return array */ public function flattenIdentifier(ClassMetadata $class, array $id) { $flatId = array(); foreach ($class->identifier as $field) { if (isset($class->associationMappings[$field]) && isset($id[$field]) && is_object($id[$field])) { /* @var $targetClassMetadata ClassMetadata */ $targetClassMetadata = $this->metadataFactory->getMetadataFor($class->associationMappings[$field]['targetEntity']); if ($this->unitOfWork->isInIdentityMap($id[$field])) { $associatedId = $this->flattenIdentifier($targetClassMetadata, $this->unitOfWork->getEntityIdentifier($id[$field])); } else { $associatedId = $this->flattenIdentifier($targetClassMetadata, $targetClassMetadata->getIdentifierValues($id[$field])); } $flatId[$field] = implode(' ', $associatedId); } elseif (isset($class->associationMappings[$field])) { $associatedId = array(); foreach ($class->associationMappings[$field]['joinColumns'] as $joinColumn) { $associatedId[] = $id[$joinColumn['name']]; } $flatId[$field] = implode(' ', $associatedId); } else { $flatId[$field] = $id[$field]; } } return $flatId; }
/** * {@inheritdoc} */ public function buildCacheEntry(ClassMetadata $metadata, EntityCacheKey $key, $entity) { $data = $this->uow->getOriginalEntityData($entity); $data = array_merge($data, $key->identifier); // why update has no identifier values ? foreach ($metadata->associationMappings as $name => $assoc) { if (!isset($data[$name])) { continue; } if (!isset($assoc['cache']) || !($assoc['type'] & ClassMetadata::TO_ONE)) { unset($data[$name]); continue; } if (!isset($assoc['id'])) { $targetClass = ClassUtils::getClass($data[$name]); $targetId = $this->uow->getEntityIdentifier($data[$name]); $data[$name] = new AssociationCacheEntry($targetClass, $targetId); continue; } // handle association identifier $targetId = is_object($data[$name]) && $this->uow->isInIdentityMap($data[$name]) ? $this->uow->getEntityIdentifier($data[$name]) : $data[$name]; // @TODO - fix it ! // handle UnitOfWork#createEntity hash generation if (!is_array($targetId)) { $data[reset($assoc['joinColumnFieldNames'])] = $targetId; $targetEntity = $this->em->getClassMetadata($assoc['targetEntity']); $targetId = array($targetEntity->identifier[0] => $targetId); } $data[$name] = new AssociationCacheEntry($assoc['targetEntity'], $targetId); } return new EntityCacheEntry($metadata->name, $data); }
/** * {@inheritdoc} */ public function buildCacheEntry(ClassMetadata $metadata, CollectionCacheKey $key, $collection) { $data = []; foreach ($collection as $index => $entity) { $data[$index] = new EntityCacheKey($metadata->name, $this->uow->getEntityIdentifier($entity)); } return new CollectionCacheEntry($data); }
/** * convert foreign identifiers into scalar foreign key values to avoid object to string conversion failures. * * @param \Doctrine\ORM\Mapping\ClassMetadata $class * @param array $id * @return array */ public function flattenIdentifier(ClassMetadata $class, array $id) { $flatId = array(); foreach ($id as $idField => $idValue) { if (isset($class->associationMappings[$idField]) && is_object($idValue)) { $targetClassMetadata = $this->metadataFactory->getMetadataFor($class->associationMappings[$idField]['targetEntity']); $associatedId = $this->unitOfWork->getEntityIdentifier($idValue); $flatId[$idField] = $associatedId[$targetClassMetadata->identifier[0]]; } else { $flatId[$idField] = $idValue; } } return $flatId; }
/** * @param \Doctrine\ORM\Cache\QueryCacheKey $key * @param array $assoc * @param mixed $assocValue * * @return array|null */ private function storeAssociationCache(QueryCacheKey $key, array $assoc, $assocValue) { $assocPersister = $this->uow->getEntityPersister($assoc['targetEntity']); $assocMetadata = $assocPersister->getClassMetadata(); $assocRegion = $assocPersister->getCacheRegion(); // Handle *-to-one associations if ($assoc['type'] & ClassMetadata::TO_ONE) { $assocIdentifier = $this->uow->getEntityIdentifier($assocValue); $entityKey = new EntityCacheKey($assocMetadata->rootEntityName, $assocIdentifier); if (!$assocValue instanceof Proxy && $key->cacheMode & Cache::MODE_REFRESH || !$assocRegion->contains($entityKey)) { // Entity put fail if (!$assocPersister->storeEntityCache($assocValue, $entityKey)) { return null; } } return ['targetEntity' => $assocMetadata->rootEntityName, 'identifier' => $assocIdentifier, 'type' => $assoc['type']]; } // Handle *-to-many associations $list = []; foreach ($assocValue as $assocItemIndex => $assocItem) { $assocIdentifier = $this->uow->getEntityIdentifier($assocItem); $entityKey = new EntityCacheKey($assocMetadata->rootEntityName, $assocIdentifier); if ($key->cacheMode & Cache::MODE_REFRESH || !$assocRegion->contains($entityKey)) { // Entity put fail if (!$assocPersister->storeEntityCache($assocItem, $entityKey)) { return null; } } $list[$assocItemIndex] = $assocIdentifier; } return ['targetEntity' => $assocMetadata->rootEntityName, 'type' => $assoc['type'], 'list' => $list]; }
/** * @param ClassMetadata $class * @param array $entityData * @param string $revType */ private function saveRevisionEntityData($class, $entityData, $revType) { $params = array($this->getRevisionId(), $revType); $types = array(\PDO::PARAM_INT, \PDO::PARAM_STR); $fields = array(); foreach ($class->associationMappings as $field => $assoc) { if (($assoc['type'] & ClassMetadata::TO_ONE) > 0 && $assoc['isOwningSide']) { $targetClass = $this->em->getClassMetadata($assoc['targetEntity']); if ($entityData[$field] !== null) { $relatedId = $this->uow->getEntityIdentifier($entityData[$field]); } $targetClass = $this->em->getClassMetadata($assoc['targetEntity']); foreach ($assoc['sourceToTargetKeyColumns'] as $sourceColumn => $targetColumn) { $fields[$sourceColumn] = true; if ($entityData[$field] === null) { $params[] = null; $types[] = \PDO::PARAM_STR; } else { $params[] = $relatedId[$targetClass->fieldNames[$targetColumn]]; $types[] = $targetClass->getTypeOfColumn($targetColumn); } } } } foreach ($class->fieldNames as $field) { if (array_key_exists($field, $fields)) { continue; } $params[] = $entityData[$field]; $types[] = $class->fieldMappings[$field]['type']; } $this->conn->executeUpdate($this->getInsertRevisionSQL($class), $params, $types); }
/** * {@inheritdoc} */ public function count(PersistentCollection $collection) { $ownerId = $this->uow->getEntityIdentifier($collection->getOwner()); $key = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association['fieldName'], $ownerId); $entry = $this->region->get($key); if ($entry !== null) { return count($entry->identifiers); } return $this->persister->count($collection); }
/** * @param string $targetEntity * @param object $element */ protected function evictElementCache($targetEntity, $element) { /* @var $targetPersister CachedEntityPersister */ $targetPersister = $this->uow->getEntityPersister($targetEntity); $targetRegion = $targetPersister->getCacheRegion(); $key = new EntityCacheKey($targetEntity, $this->uow->getEntityIdentifier($element)); $targetRegion->evict($key); if ($this->cacheLogger) { $this->cacheLogger->entityCachePut($targetRegion->getName(), $key); } }
/** * @param mixed $data * @param bool $includeCollectionTag * @param bool $processNestedData * @return array */ protected function getTags($data, $includeCollectionTag, $processNestedData) { $tags = []; $class = ClassUtils::getRealClass($data); if (is_object($data)) { // tag only in case if it's not a new object if ($this->isNewEntity($data)) { $identifier = $this->uow->getEntityIdentifier($data); $tag = $this->convertToTag($class); $tags[] = implode('_', array_merge([$tag], $identifier)); if ($processNestedData) { $tags = array_merge($tags, $this->collectNestedDataTags($data)); } } } if ($includeCollectionTag && $class !== null) { $tags[] = $this->convertToTag($class) . self::COLLECTION_SUFFIX; } return $tags; }
/** * @param ClassMetadata $class * @param array $entityData * @param string $revType */ private function saveRevisionEntityData($class, $entityData, $revType) { $params = array($this->getRevisionId(), $revType); $types = array(\PDO::PARAM_INT, \PDO::PARAM_STR); $fields = array(); foreach ($class->associationMappings as $field => $assoc) { if ($class->isInheritanceTypeJoined() && $class->isInheritedAssociation($field)) { continue; } if (($assoc['type'] & ClassMetadata::TO_ONE) > 0 && $assoc['isOwningSide']) { $data = isset($entityData[$field]) ? $entityData[$field] : null; $relatedId = false; if ($data !== null && $this->uow->isInIdentityMap($data)) { $relatedId = $this->uow->getEntityIdentifier($data); } $targetClass = $this->em->getClassMetadata($assoc['targetEntity']); foreach ($assoc['sourceToTargetKeyColumns'] as $sourceColumn => $targetColumn) { $fields[$sourceColumn] = true; if ($data === null) { $params[] = null; $types[] = \PDO::PARAM_STR; } else { $params[] = $relatedId ? $relatedId[$targetClass->fieldNames[$targetColumn]] : null; $types[] = $targetClass->getTypeOfColumn($targetColumn); } } } } foreach ($class->fieldNames as $field) { if (array_key_exists($field, $fields)) { continue; } if ($class->isInheritanceTypeJoined() && $class->isInheritedField($field) && !$class->isIdentifier($field)) { continue; } $params[] = isset($entityData[$field]) ? $entityData[$field] : null; $types[] = $class->fieldMappings[$field]['type']; } if ($class->isInheritanceTypeSingleTable()) { $params[] = $class->discriminatorValue; $types[] = $class->discriminatorColumn['type']; } elseif ($class->isInheritanceTypeJoined() && $class->name == $class->rootEntityName) { $params[] = $entityData[$class->discriminatorColumn['name']]; $types[] = $class->discriminatorColumn['type']; } if ($class->isInheritanceTypeJoined() && $class->name != $class->rootEntityName && count($class->parentClasses)) { if (!isset($entityData[$class->discriminatorColumn['name']])) { $entityData[$class->discriminatorColumn['name']] = $class->discriminatorValue; } $this->saveRevisionEntityData($this->em->getClassMetadata($class->parentClasses[0]), $entityData, $revType); } $this->conn->executeUpdate($this->getInsertRevisionSQL($class), $params, $types); }
/** * {@inheritdoc} */ public function buildCacheEntry(ClassMetadata $metadata, EntityCacheKey $key, $entity) { $data = $this->uow->getOriginalEntityData($entity); $data = array_merge($data, $metadata->getIdentifierValues($entity)); // why update has no identifier values ? foreach ($metadata->associationMappings as $name => $assoc) { if (!isset($data[$name])) { continue; } if (!($assoc['type'] & ClassMetadata::TO_ONE)) { unset($data[$name]); continue; } if (!isset($assoc['cache'])) { $targetClassMetadata = $this->em->getClassMetadata($assoc['targetEntity']); $owningAssociation = !$assoc['isOwningSide'] ? $targetClassMetadata->associationMappings[$assoc['mappedBy']] : $assoc; $associationIds = $this->identifierFlattener->flattenIdentifier($targetClassMetadata, $targetClassMetadata->getIdentifierValues($data[$name])); unset($data[$name]); foreach ($associationIds as $fieldName => $fieldValue) { if (isset($targetClassMetadata->fieldMappings[$fieldName])) { $fieldMapping = $targetClassMetadata->fieldMappings[$fieldName]; $data[$owningAssociation['targetToSourceKeyColumns'][$fieldMapping['columnName']]] = $fieldValue; continue; } $targetAssoc = $targetClassMetadata->associationMappings[$fieldName]; foreach ($assoc['targetToSourceKeyColumns'] as $referencedColumn => $localColumn) { if (isset($targetAssoc['sourceToTargetKeyColumns'][$referencedColumn])) { $data[$localColumn] = $fieldValue; } } } continue; } if (!isset($assoc['id'])) { $targetClass = ClassUtils::getClass($data[$name]); $targetId = $this->uow->getEntityIdentifier($data[$name]); $data[$name] = new AssociationCacheEntry($targetClass, $targetId); continue; } // handle association identifier $targetId = is_object($data[$name]) && $this->uow->isInIdentityMap($data[$name]) ? $this->uow->getEntityIdentifier($data[$name]) : $data[$name]; // @TODO - fix it ! // handle UnitOfWork#createEntity hash generation if (!is_array($targetId)) { $data[reset($assoc['joinColumnFieldNames'])] = $targetId; $targetEntity = $this->em->getClassMetadata($assoc['targetEntity']); $targetId = [$targetEntity->identifier[0] => $targetId]; } $data[$name] = new AssociationCacheEntry($assoc['targetEntity'], $targetId); } return new EntityCacheEntry($metadata->name, $data); }
private function getUniqueAndRequiredAssociations(ClassMetadata $meta, $entity) { $associations = array(); foreach ($meta->getAssociationNames() as $associationName) { $mapping = $meta->getAssociationMapping($associationName); if (!empty($mapping['id']) && $meta->usesIdGenerator()) { // autogenerated id continue; } if (!($mapping['type'] & ClassMetadata::TO_ONE)) { // is not to one relation continue; } if (empty($mapping['isOwningSide'])) { // is not owning side continue; } foreach ($mapping['joinColumns'] as $joinColumn) { if (!empty($joinColumn['nullable']) && empty($joinColumn['unique'])) { // is nullable and is not unique continue; } $targetColumn = $joinColumn['referencedColumnName']; $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); $newVal = $meta->getFieldValue($entity, $associationName); if ($newVal !== NULL) { $newValId = $this->uow->getEntityIdentifier($newVal); } switch (TRUE) { case $newVal === NULL: $value = NULL; break; case $targetClass->containsForeignIdentifier: $value = $newValId[$targetClass->getFieldForColumn($targetColumn)]; break; default: $value = $newValId[$targetClass->fieldNames[$targetColumn]]; break; } $sourceColumn = $joinColumn['name']; $quotedColumn = $this->quotes->getJoinColumnName($joinColumn, $meta, $this->platform); $associations[$sourceColumn]['value'] = $value; $associations[$sourceColumn]['quotedColumn'] = $quotedColumn; $associations[$sourceColumn]['type'] = $targetClass->getTypeOfColumn($targetColumn); } } return $associations; }
/** * {@inheritdoc} */ public function loadOneToManyCollection(array $assoc, $sourceEntity, PersistentCollection $coll) { $persister = $this->uow->getCollectionPersister($assoc); $hasCache = $persister instanceof CachedPersister; if ($hasCache) { $ownerId = $this->uow->getEntityIdentifier($coll->getOwner()); $key = new CollectionCacheKey($assoc['sourceEntity'], $assoc['fieldName'], $ownerId); $list = $persister->loadCollectionCache($coll, $key); if ($list !== null) { if ($this->cacheLogger) { $this->cacheLogger->collectionCacheHit($persister->getCacheRegion()->getName(), $key); } return $list; } } $list = $this->persister->loadOneToManyCollection($assoc, $sourceEntity, $coll); if ($hasCache) { $persister->storeCollectionCache($key, $list); if ($this->cacheLogger) { $this->cacheLogger->collectionCacheMiss($persister->getCacheRegion()->getName(), $key); } } return $list; }
/** * {@inheritdoc} */ public function put(QueryCacheKey $key, ResultSetMapping $rsm, $result, array $hints = array()) { if ($rsm->scalarMappings) { throw new CacheException("Second level cache does not support scalar results."); } if (count($rsm->entityMappings) > 1) { throw new CacheException("Second level cache does not support multiple root entities."); } if (!$rsm->isSelect) { throw new CacheException("Second-level cache query supports only select statements."); } if (isset($hints[Query::HINT_FORCE_PARTIAL_LOAD]) && $hints[Query::HINT_FORCE_PARTIAL_LOAD]) { throw new CacheException("Second level cache does not support partial entities."); } if (!($key->cacheMode & Cache::MODE_PUT)) { return false; } $data = array(); $entityName = reset($rsm->aliasMap); $hasRelation = !empty($rsm->relationMap); $metadata = $this->em->getClassMetadata($entityName); $persister = $this->uow->getEntityPersister($entityName); if (!$persister instanceof CachedPersister) { throw CacheException::nonCacheableEntity($entityName); } $region = $persister->getCacheRegion(); foreach ($result as $index => $entity) { $identifier = $this->uow->getEntityIdentifier($entity); $data[$index]['identifier'] = $identifier; $data[$index]['associations'] = array(); if ($key->cacheMode & Cache::MODE_REFRESH || !$region->contains($entityKey = new EntityCacheKey($entityName, $identifier))) { // Cancel put result if entity put fail if (!$persister->storeEntityCache($entity, $entityKey)) { return false; } } if (!$hasRelation) { continue; } // @TODO - move to cache hydration components foreach ($rsm->relationMap as $name) { $assoc = $metadata->associationMappings[$name]; if (($assocValue = $metadata->getFieldValue($entity, $name)) === null || $assocValue instanceof Proxy) { continue; } if (!isset($assoc['cache'])) { throw CacheException::nonCacheableEntityAssociation($entityName, $name); } $assocPersister = $this->uow->getEntityPersister($assoc['targetEntity']); $assocRegion = $assocPersister->getCacheRegion(); $assocMetadata = $assocPersister->getClassMetadata(); // Handle *-to-one associations if ($assoc['type'] & ClassMetadata::TO_ONE) { $assocIdentifier = $this->uow->getEntityIdentifier($assocValue); if ($key->cacheMode & Cache::MODE_REFRESH || !$assocRegion->contains($entityKey = new EntityCacheKey($assocMetadata->rootEntityName, $assocIdentifier))) { // Cancel put result if association entity put fail if (!$assocPersister->storeEntityCache($assocValue, $entityKey)) { return false; } } $data[$index]['associations'][$name] = array('targetEntity' => $assocMetadata->rootEntityName, 'identifier' => $assocIdentifier, 'type' => $assoc['type']); continue; } // Handle *-to-many associations $list = array(); foreach ($assocValue as $assocItemIndex => $assocItem) { $assocIdentifier = $this->uow->getEntityIdentifier($assocItem); if ($key->cacheMode & Cache::MODE_REFRESH || !$assocRegion->contains($entityKey = new EntityCacheKey($assocMetadata->rootEntityName, $assocIdentifier))) { // Cancel put result if entity put fail if (!$assocPersister->storeEntityCache($assocItem, $entityKey)) { return false; } } $list[$assocItemIndex] = $assocIdentifier; } $data[$index]['associations'][$name] = array('targetEntity' => $assocMetadata->rootEntityName, 'type' => $assoc['type'], 'list' => $list); } } return $this->region->put($key, new QueryCacheEntry($data)); }
/** * @param object $entity * @param UnitOfWork $uow * * @return string */ private function getIdString($entity, UnitOfWork $uow) { if ($uow->isInIdentityMap($entity)) { $ids = $uow->getEntityIdentifier($entity); $idstring = ""; foreach ($ids as $k => $v) { $idstring .= $k . "=" . $v; } } else { $idstring = "NEWOBJECT "; } $state = $uow->getEntityState($entity); if ($state == UnitOfWork::STATE_NEW) { $idstring .= " [NEW]"; } elseif ($state == UnitOfWork::STATE_REMOVED) { $idstring .= " [REMOVED]"; } elseif ($state == UnitOfWork::STATE_MANAGED) { $idstring .= " [MANAGED]"; } elseif ($state == UnitOfwork::STATE_DETACHED) { $idstring .= " [DETACHED]"; } return $idstring; }
/** * @param $entity * * @return string */ private function getHash($entity) { return implode(' ', array_merge(array(get_class($entity)), $this->uow->getEntityIdentifier($entity))); }