Doctrine\ORM\UnitOfWork::createEntity PHP Method

createEntity() public method

INTERNAL: Creates an entity. Used for reconstitution of persistent entities.
public createEntity ( string $className, array $data, array &$hints = [] ) : object
$className string The name of the entity class.
$data array The data for the entity.
$hints array Any hints to account for during reconstitution/lookup of the entity.
return object The managed entity instance.
    public function createEntity($className, array $data, &$hints = array())
    {
        $class = $this->em->getClassMetadata($className);
        //$isReadOnly = isset($hints[Query::HINT_READ_ONLY]);

        if ($class->isIdentifierComposite) {
            $id = array();
            foreach ($class->identifier as $fieldName) {
                $id[$fieldName] = $data[$fieldName];
            }
            $idHash = implode(' ', $id);
        } else {
            $idHash = $data[$class->identifier[0]];
            $id = array($class->identifier[0] => $idHash);
        }

        if (isset($this->identityMap[$class->rootEntityName][$idHash])) {
            $entity = $this->identityMap[$class->rootEntityName][$idHash];
            $oid = spl_object_hash($entity);
            if ($entity instanceof Proxy && ! $entity->__isInitialized__) {
                $entity->__isInitialized__ = true;
                $overrideLocalValues = true;
                $this->originalEntityData[$oid] = $data;
                if ($entity instanceof NotifyPropertyChanged) {
                    $entity->addPropertyChangedListener($this);
                }
            } else {
                $overrideLocalValues = isset($hints[Query::HINT_REFRESH]);
            }
        } else {
            $entity = $class->newInstance();
            $oid = spl_object_hash($entity);
            $this->entityIdentifiers[$oid] = $id;
            $this->entityStates[$oid] = self::STATE_MANAGED;
            $this->originalEntityData[$oid] = $data;
            $this->identityMap[$class->rootEntityName][$idHash] = $entity;
            if ($entity instanceof NotifyPropertyChanged) {
                $entity->addPropertyChangedListener($this);
            }
            $overrideLocalValues = true;
        }

        if ($overrideLocalValues) {
            foreach ($data as $field => $value) {
                if (isset($class->fieldMappings[$field])) {
                    $class->reflFields[$field]->setValue($entity, $value);
                }
            }
            
            // Properly initialize any unfetched associations, if partial objects are not allowed.
            if ( ! isset($hints[Query::HINT_FORCE_PARTIAL_LOAD])) {
                foreach ($class->associationMappings as $field => $assoc) {
                    // Check if the association is not among the fetch-joined associations already.
                    if (isset($hints['fetched'][$className][$field])) {
                        continue;
                    }

                    $targetClass = $this->em->getClassMetadata($assoc['targetEntity']);

                    if ($assoc['type'] & ClassMetadata::TO_ONE) {
                        if ($assoc['isOwningSide']) {
                            $associatedId = array();
                            foreach ($assoc['targetToSourceKeyColumns'] as $targetColumn => $srcColumn) {
                                $joinColumnValue = isset($data[$srcColumn]) ? $data[$srcColumn] : null;
                                if ($joinColumnValue !== null) {
                                    $associatedId[$targetClass->fieldNames[$targetColumn]] = $joinColumnValue;
                                }
                            }
                            if ( ! $associatedId) {
                                // Foreign key is NULL
                                $class->reflFields[$field]->setValue($entity, null);
                                $this->originalEntityData[$oid][$field] = null;
                            } else {
                                // Foreign key is set
                                // Check identity map first
                                // FIXME: Can break easily with composite keys if join column values are in
                                //        wrong order. The correct order is the one in ClassMetadata#identifier.
                                $relatedIdHash = implode(' ', $associatedId);
                                if (isset($this->identityMap[$targetClass->rootEntityName][$relatedIdHash])) {
                                    $newValue = $this->identityMap[$targetClass->rootEntityName][$relatedIdHash];
                                } else {
                                    if ($targetClass->subClasses) {
                                        // If it might be a subtype, it can not be lazy
                                        $newValue = $this->getEntityPersister($assoc['targetEntity'])
                                                ->loadOneToOneEntity($assoc, $entity, null, $associatedId);
                                    } else {
                                        if ($assoc['fetch'] == ClassMetadata::FETCH_EAGER) {
                                            // TODO: Maybe it could be optimized to do an eager fetch with a JOIN inside
                                            // the persister instead of this rather unperformant approach.
                                            $newValue = $this->em->find($assoc['targetEntity'], $associatedId);
                                        } else {
                                            $newValue = $this->em->getProxyFactory()->getProxy($assoc['targetEntity'], $associatedId);
                                        }
                                        // PERF: Inlined & optimized code from UnitOfWork#registerManaged()
                                        $newValueOid = spl_object_hash($newValue);
                                        $this->entityIdentifiers[$newValueOid] = $associatedId;
                                        $this->identityMap[$targetClass->rootEntityName][$relatedIdHash] = $newValue;
                                        $this->entityStates[$newValueOid] = self::STATE_MANAGED;
                                        // make sure that when an proxy is then finally loaded, $this->originalEntityData is set also!
                                    }
                                }
                                $this->originalEntityData[$oid][$field] = $newValue;
                                $class->reflFields[$field]->setValue($entity, $newValue);
                            }
                        } else {
                            // Inverse side of x-to-one can never be lazy
                            $class->reflFields[$field]->setValue($entity, $this->getEntityPersister($assoc['targetEntity'])
                                    ->loadOneToOneEntity($assoc, $entity, null));
                        }
                    } else {
                        // Inject collection
                        $pColl = new PersistentCollection($this->em, $targetClass, new ArrayCollection);
                        $pColl->setOwner($entity, $assoc);
                        
                        $reflField = $class->reflFields[$field];
                        $reflField->setValue($entity, $pColl);
                        
                        if ($assoc['fetch'] == ClassMetadata::FETCH_LAZY) {
                            $pColl->setInitialized(false);
                        } else {
                            $this->loadCollection($pColl);
                            $pColl->takeSnapshot();
                        }
                        $this->originalEntityData[$oid][$field] = $pColl;
                    }
                }
            }
        }
        
        //TODO: These should be invoked later, after hydration, because associations may not yet be loaded here.
        if (isset($class->lifecycleCallbacks[Events::postLoad])) {
            $class->invokeLifecycleCallbacks(Events::postLoad, $entity);
        }
        if ($this->evm->hasListeners(Events::postLoad)) {
            $this->evm->dispatchEvent(Events::postLoad, new LifecycleEventArgs($entity, $this->em));
        }

        return $entity;
    }

Usage Example

 /**
  * {@inheritdoc}
  */
 public function loadCacheEntry(ClassMetadata $metadata, EntityCacheKey $key, EntityCacheEntry $entry, $entity = null)
 {
     $data = $entry->data;
     $hints = self::$hints;
     if ($entity !== null) {
         $hints[Query::HINT_REFRESH] = true;
         $hints[Query::HINT_REFRESH_ENTITY] = $entity;
     }
     foreach ($metadata->associationMappings as $name => $assoc) {
         if (!isset($assoc['cache']) || !isset($data[$name])) {
             continue;
         }
         $assocClass = $data[$name]->class;
         $assocId = $data[$name]->identifier;
         $isEagerLoad = $assoc['fetch'] === ClassMetadata::FETCH_EAGER || $assoc['type'] === ClassMetadata::ONE_TO_ONE && !$assoc['isOwningSide'];
         if (!$isEagerLoad) {
             $data[$name] = $this->em->getReference($assocClass, $assocId);
             continue;
         }
         $assocKey = new EntityCacheKey($assoc['targetEntity'], $assocId);
         $assocPersister = $this->uow->getEntityPersister($assoc['targetEntity']);
         $assocRegion = $assocPersister->getCacheRegion();
         $assocEntry = $assocRegion->get($assocKey);
         if ($assocEntry === null) {
             return null;
         }
         $data[$name] = $this->uow->createEntity($assocEntry->class, $assocEntry->resolveAssociationEntries($this->em), $hints);
     }
     if ($entity !== null) {
         $this->uow->registerManaged($entity, $key->identifier, $data);
     }
     $result = $this->uow->createEntity($entry->class, $data, $hints);
     $this->uow->hydrationComplete();
     return $result;
 }
All Usage Examples Of Doctrine\ORM\UnitOfWork::createEntity