Gets the proxy factory used by the EntityManager to create entity proxies.
public getProxyFactory ( ) : Doctrine\ORM\Proxy\ProxyFactory | ||
return | Doctrine\ORM\Proxy\ProxyFactory |
public function update(GenericEvent $event) { $tool = new \Doctrine\ORM\Tools\SchemaTool($this->em); $tool->updateSchema($this->getClasses(), true); // Generate proxies for entities $this->em->getProxyFactory()->generateProxyClasses($this->getClasses(), __DIR__ . '/../../../../library/Proxy'); // Update articletype $this->articleTypeConfigurationService->update(); // Register parsers $this->dispatcher->dispatch('newscoop_ingest.parser.register', new IngestParsersEvent($this, array())); // Only add if the job doesn't exist $this->updateJobs(); // Set persissions $this->setPermissions(); }
/** * Generate doctrine proxy classes for extended entities for the given entity manager * * @param EntityManager $em */ protected function generateEntityManagerProxies(EntityManager $em) { $isAutoGenerated = $em->getConfiguration()->getAutoGenerateProxyClasses(); if (!$isAutoGenerated) { $proxyDir = $em->getConfiguration()->getProxyDir(); if (!empty($this->cacheDir) && $this->kernelCacheDir !== $this->cacheDir && strpos($proxyDir, $this->kernelCacheDir) === 0) { $proxyDir = $this->cacheDir . substr($proxyDir, strlen($this->kernelCacheDir)); } $metadataFactory = $em->getMetadataFactory(); $proxyFactory = $em->getProxyFactory(); $extendConfigs = $this->extendConfigProvider->getConfigs(null, true); foreach ($extendConfigs as $extendConfig) { if (!$extendConfig->is('is_extend')) { continue; } if ($extendConfig->in('state', [ExtendScope::STATE_NEW])) { continue; } $entityClass = $extendConfig->getId()->getClassName(); $proxyFileName = $proxyDir . DIRECTORY_SEPARATOR . '__CG__' . str_replace('\\', '', $entityClass) . '.php'; $metadata = $metadataFactory->getMetadataFor($entityClass); $proxyFactory->generateProxyClasses([$metadata], $proxyDir); clearstatcache(true, $proxyFileName); } } }
/** * @throws \Doctrine\ORM\ORMException */ public function boot() { $this->serializer = SerializerBuilder::create()->setDebug($this->devMode)->build(); $this->entityFolder->create(); AnnotationRegistry::registerAutoloadNamespace('JMS\\Serializer\\Annotation', __DIR__ . '/../../../../vendor/jms/serializer/src'); $proxyDoctrineFolder = new Folder(sys_get_temp_dir() . '/doctrine'); $config = Setup::createAnnotationMetadataConfiguration([$this->entityFolder->absolute()], $this->isDevMode(), $proxyDoctrineFolder->absolute()); if ($this->cache !== null) { $config->setQueryCacheImpl($this->getCache()); $config->setResultCacheImpl($this->getCache()); } $this->entityManager = $this->createEntityManager($config); $debugStack = new DebugStack(); $this->entityManager->getConnection()->getConfiguration()->setSQLLogger($debugStack); if ($this->getFileCreation()->getContent() == 1) { return; } if ($proxyDoctrineFolder->isFolder()) { $proxyDoctrineFolder->removeFiles(); } $tool = new SchemaTool($this->entityManager); $metadatas = $this->entityManager->getMetadataFactory()->getAllMetadata(); $proxyDoctrineFolder->create(); $this->entityManager->getProxyFactory()->generateProxyClasses($metadatas, $proxyDoctrineFolder->absolute()); if ($this->cloudFoundryBoot->isInCloudFoundry()) { $tool->updateSchema($metadatas); } else { $tool->createSchema($metadatas); } $this->getFileCreation()->setContent(1); }
/** * Setup system, not included in benchmark. */ public function setUp() { require_once $this->rootPath . "/lib/Doctrine/ORM/Version.php"; if (version_compare(\Doctrine\ORM\Version::VERSION, '2.3.99') > 0) { require_once $this->rootPath . "/vendor/autoload.php"; $config = \Doctrine\ORM\Tools\Setup::createAnnotationMetadataConfiguration(array(__DIR__ . "/Orm")); } else { if (version_compare(\Doctrine\ORM\Version::VERSION, '2.2.99') > 0) { require_once $this->rootPath . "/lib/Doctrine/ORM/Tools/Setup.php"; \Doctrine\ORM\Tools\Setup::registerAutoloadGit($this->rootPath); $config = \Doctrine\ORM\Tools\Setup::createAnnotationMetadataConfiguration(array(__DIR__ . "/Orm")); } else { require_once $this->rootPath . "/lib/vendor/doctrine-common/lib/Doctrine/Common/ClassLoader.php"; $loader = new \Doctrine\Common\ClassLoader("Doctrine\\ORM", $this->rootPath . "/lib/"); $loader->register(); $loader = new \Doctrine\Common\ClassLoader("Doctrine\\DBAL", $this->rootPath . "/lib/vendor/doctrine-dbal/lib"); $loader->register(); $loader = new \Doctrine\Common\ClassLoader("Doctrine\\Common", $this->rootPath . "/lib/vendor/doctrine-common/lib"); $loader->register(); $config = new \Doctrine\ORM\Configuration(); $config->setMetadataDriverImpl($config->newDefaultAnnotationDriver(__DIR__ . "/Orm")); } } $cache = new \Doctrine\Common\Cache\ArrayCache(); $this->queryCount = new DbalQueryCountLogger(); $config->setMetadataCacheImpl($cache); $config->setQueryCacheImpl($cache); // not sql query cache, but dql query parsing cache. $config->setProxyDir(__DIR__ . "/proxies"); $config->setProxyNamespace('Proxies'); $config->setAutoGenerateProxyClasses(false); $config->setSQLLogger($this->queryCount); $dbParams = array('driver' => 'pdo_sqlite', 'memory' => true); $this->em = \Doctrine\ORM\EntityManager::create($dbParams, $config); $classes = $this->em->getMetadataFactory()->getAllMetadata(); $schemaTool = new \Doctrine\ORM\Tools\SchemaTool($this->em); try { $schemaTool->dropSchema($classes); } catch (Exception $e) { echo $e->getMessage(); } $schemaTool->createSchema($classes); $this->em->getProxyFactory()->generateProxyClasses($classes, __DIR__ . '/proxies'); }
/** * INTERNAL: * Creates an entity. Used for reconstitution of persistent entities. * * @ignore * * @param string $className The name of the entity class. * @param array $data The data for the entity. * @param array $hints Any hints to account for during reconstitution/lookup of the entity. * * @return object The managed entity instance. * * @internal Highly performance-sensitive method. * * @todo Rename: getOrCreateEntity */ 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] = isset($class->associationMappings[$fieldName]) ? $data[$class->associationMappings[$fieldName]['joinColumns'][0]['name']] : $data[$fieldName]; } } else { $id = isset($class->associationMappings[$class->identifier[0]]) ? $data[$class->associationMappings[$class->identifier[0]]['joinColumns'][0]['name']] : $data[$class->identifier[0]]; $id = array($class->identifier[0] => $id); } $idHash = implode(' ', $id); if (isset($this->identityMap[$class->rootEntityName][$idHash])) { $entity = $this->identityMap[$class->rootEntityName][$idHash]; $oid = spl_object_hash($entity); if (isset($hints[Query::HINT_REFRESH]) && isset($hints[Query::HINT_REFRESH_ENTITY]) && ($unmanagedProxy = $hints[Query::HINT_REFRESH_ENTITY]) !== $entity && $unmanagedProxy instanceof Proxy && $this->isIdentifierEquals($unmanagedProxy, $entity)) { // DDC-1238 - we have a managed instance, but it isn't the provided one. // Therefore we clear its identifier. Also, we must re-fetch metadata since the // refreshed object may be anything foreach ($class->identifier as $fieldName) { $class->reflFields[$fieldName]->setValue($unmanagedProxy, null); } return $unmanagedProxy; } if ($entity instanceof Proxy && !$entity->__isInitialized()) { $entity->__setInitialized(true); $overrideLocalValues = true; if ($entity instanceof NotifyPropertyChanged) { $entity->addPropertyChangedListener($this); } } else { $overrideLocalValues = isset($hints[Query::HINT_REFRESH]); // If only a specific entity is set to refresh, check that it's the one if (isset($hints[Query::HINT_REFRESH_ENTITY])) { $overrideLocalValues = $hints[Query::HINT_REFRESH_ENTITY] === $entity; } } if ($overrideLocalValues) { // inject ObjectManager upon refresh. if ($entity instanceof ObjectManagerAware) { $entity->injectObjectManager($this->em, $class); } $this->originalEntityData[$oid] = $data; } } else { $entity = $this->newInstance($class); $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) { return $entity; } foreach ($data as $field => $value) { if (isset($class->fieldMappings[$field])) { $class->reflFields[$field]->setValue($entity, $value); } } // Loading the entity right here, if its in the eager loading map get rid of it there. unset($this->eagerLoadingEntities[$class->rootEntityName][$idHash]); if (isset($this->eagerLoadingEntities[$class->rootEntityName]) && !$this->eagerLoadingEntities[$class->rootEntityName]) { unset($this->eagerLoadingEntities[$class->rootEntityName]); } // Properly initialize any unfetched associations, if partial objects are not allowed. if (isset($hints[Query::HINT_FORCE_PARTIAL_LOAD])) { return $entity; } foreach ($class->associationMappings as $field => $assoc) { // Check if the association is not among the fetch-joined associations already. if (isset($hints['fetchAlias']) && isset($hints['fetched'][$hints['fetchAlias']][$field])) { continue; } $targetClass = $this->em->getClassMetadata($assoc['targetEntity']); switch (true) { case $assoc['type'] & ClassMetadata::TO_ONE: if (!$assoc['isOwningSide']) { // use the given entity association if (isset($data[$field]) && is_object($data[$field]) && isset($this->entityStates[spl_object_hash($data[$field])])) { $this->originalEntityData[$oid][$field] = $data[$field]; $class->reflFields[$field]->setValue($entity, $data[$field]); $targetClass->reflFields[$assoc['mappedBy']]->setValue($data[$field], $entity); continue 2; } // Inverse side of x-to-one can never be lazy $class->reflFields[$field]->setValue($entity, $this->getEntityPersister($assoc['targetEntity'])->loadOneToOneEntity($assoc, $entity)); continue 2; } // use the entity association if (isset($data[$field]) && is_object($data[$field]) && isset($this->entityStates[spl_object_hash($data[$field])])) { $class->reflFields[$field]->setValue($entity, $data[$field]); $this->originalEntityData[$oid][$field] = $data[$field]; continue; } $associatedId = array(); // TODO: Is this even computed right in all cases of composite keys? foreach ($assoc['targetToSourceKeyColumns'] as $targetColumn => $srcColumn) { $joinColumnValue = isset($data[$srcColumn]) ? $data[$srcColumn] : null; if ($joinColumnValue !== null) { if ($targetClass->containsForeignIdentifier) { $associatedId[$targetClass->getFieldForColumn($targetColumn)] = $joinColumnValue; } else { $associatedId[$targetClass->fieldNames[$targetColumn]] = $joinColumnValue; } } } if (!$associatedId) { // Foreign key is NULL $class->reflFields[$field]->setValue($entity, null); $this->originalEntityData[$oid][$field] = null; continue; } if (!isset($hints['fetchMode'][$class->name][$field])) { $hints['fetchMode'][$class->name][$field] = $assoc['fetch']; } // 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); switch (true) { case isset($this->identityMap[$targetClass->rootEntityName][$relatedIdHash]): $newValue = $this->identityMap[$targetClass->rootEntityName][$relatedIdHash]; // If this is an uninitialized proxy, we are deferring eager loads, // this association is marked as eager fetch, and its an uninitialized proxy (wtf!) // then we can append this entity for eager loading! if ($hints['fetchMode'][$class->name][$field] == ClassMetadata::FETCH_EAGER && isset($hints[self::HINT_DEFEREAGERLOAD]) && !$targetClass->isIdentifierComposite && $newValue instanceof Proxy && $newValue->__isInitialized__ === false) { $this->eagerLoadingEntities[$targetClass->rootEntityName][$relatedIdHash] = current($associatedId); } break; case $targetClass->subClasses: // If it might be a subtype, it can not be lazy. There isn't even // a way to solve this with deferred eager loading, which means putting // an entity with subclasses at a *-to-one location is really bad! (performance-wise) $newValue = $this->getEntityPersister($assoc['targetEntity'])->loadOneToOneEntity($assoc, $entity, $associatedId); break; default: switch (true) { // We are negating the condition here. Other cases will assume it is valid! case $hints['fetchMode'][$class->name][$field] !== ClassMetadata::FETCH_EAGER: $newValue = $this->em->getProxyFactory()->getProxy($assoc['targetEntity'], $associatedId); break; // Deferred eager load only works for single identifier classes // Deferred eager load only works for single identifier classes case isset($hints[self::HINT_DEFEREAGERLOAD]) && !$targetClass->isIdentifierComposite: // TODO: Is there a faster approach? $this->eagerLoadingEntities[$targetClass->rootEntityName][$relatedIdHash] = current($associatedId); $newValue = $this->em->getProxyFactory()->getProxy($assoc['targetEntity'], $associatedId); break; default: // TODO: This is very imperformant, ignore it? $newValue = $this->em->find($assoc['targetEntity'], $associatedId); break; } // PERF: Inlined & optimized code from UnitOfWork#registerManaged() $newValueOid = spl_object_hash($newValue); $this->entityIdentifiers[$newValueOid] = $associatedId; $this->identityMap[$targetClass->rootEntityName][$relatedIdHash] = $newValue; if ($newValue instanceof NotifyPropertyChanged && (!$newValue instanceof Proxy || $newValue->__isInitialized())) { $newValue->addPropertyChangedListener($this); } $this->entityStates[$newValueOid] = self::STATE_MANAGED; // make sure that when an proxy is then finally loaded, $this->originalEntityData is set also! break; } $this->originalEntityData[$oid][$field] = $newValue; $class->reflFields[$field]->setValue($entity, $newValue); if ($assoc['inversedBy'] && $assoc['type'] & ClassMetadata::ONE_TO_ONE) { $inverseAssoc = $targetClass->associationMappings[$assoc['inversedBy']]; $targetClass->reflFields[$inverseAssoc['fieldName']]->setValue($newValue, $entity); } break; default: // Ignore if its a cached collection if (isset($hints[Query::HINT_CACHE_ENABLED]) && $class->getFieldValue($entity, $field) instanceof PersistentCollection) { break; } // use the given collection if (isset($data[$field]) && $data[$field] instanceof PersistentCollection) { $data[$field]->setOwner($entity, $assoc); $class->reflFields[$field]->setValue($entity, $data[$field]); $this->originalEntityData[$oid][$field] = $data[$field]; break; } // Inject collection $pColl = new PersistentCollection($this->em, $targetClass, new ArrayCollection()); $pColl->setOwner($entity, $assoc); $pColl->setInitialized(false); $reflField = $class->reflFields[$field]; $reflField->setValue($entity, $pColl); if ($assoc['fetch'] == ClassMetadata::FETCH_EAGER) { $this->loadCollection($pColl); $pColl->takeSnapshot(); } $this->originalEntityData[$oid][$field] = $pColl; break; } } if ($overrideLocalValues) { $invoke = $this->listenersInvoker->getSubscribedSystems($class, Events::postLoad); if ($invoke !== ListenersInvoker::INVOKE_NONE) { $this->listenersInvoker->invoke($class, Events::postLoad, $entity, new LifecycleEventArgs($entity, $this->em), $invoke); } } return $entity; }
/** * Refreshes a managed entity. * * @param array $id The identifier of the entity as an associative array from * column or field names to values. * @param object $entity The entity to refresh. */ public function refresh(array $id, $entity) { $sql = $this->_getSelectEntitiesSQL($id); $stmt = $this->_conn->executeQuery($sql, array_values($id)); $result = $stmt->fetch(PDO::FETCH_ASSOC); $stmt->closeCursor(); $metaColumns = array(); $newData = array(); // Refresh simple state foreach ($result as $column => $value) { $column = $this->_resultColumnNames[$column]; if (isset($this->_class->fieldNames[$column])) { $fieldName = $this->_class->fieldNames[$column]; $newValue = $this->_conn->convertToPHPValue($value, $this->_class->fieldMappings[$fieldName]['type']); $this->_class->reflFields[$fieldName]->setValue($entity, $newValue); $newData[$fieldName] = $newValue; } else { $metaColumns[$column] = $value; } } // Refresh associations foreach ($this->_class->associationMappings as $field => $assoc) { $value = $this->_class->reflFields[$field]->getValue($entity); if ($assoc['type'] & ClassMetadata::TO_ONE) { if ($value instanceof Proxy && !$value->__isInitialized__) { continue; // skip uninitialized proxies } if ($assoc['isOwningSide']) { $joinColumnValues = array(); foreach ($assoc['targetToSourceKeyColumns'] as $targetColumn => $srcColumn) { if ($metaColumns[$srcColumn] !== null) { $joinColumnValues[$targetColumn] = $metaColumns[$srcColumn]; } } if (!$joinColumnValues && $value !== null) { $this->_class->reflFields[$field]->setValue($entity, null); $newData[$field] = null; } else { if ($value !== null) { // Check identity map first, if the entity is not there, // place a proxy in there instead. $targetClass = $this->_em->getClassMetadata($assoc['targetEntity']); if ($found = $this->_em->getUnitOfWork()->tryGetById($joinColumnValues, $targetClass->rootEntityName)) { $this->_class->reflFields[$field]->setValue($entity, $found); // Complete inverse side, if necessary. if ($assoc['inversedBy'] && $assoc['type'] & ClassMetadata::ONE_TO_ONE) { $inverseAssoc = $targetClass->associationMappings[$assoc['inversedBy']]; $targetClass->reflFields[$inverseAssoc['fieldName']]->setValue($found, $entity); } $newData[$field] = $found; } else { // FIXME: What is happening with subClassees here? $proxy = $this->_em->getProxyFactory()->getProxy($assoc['targetEntity'], $joinColumnValues); $this->_class->reflFields[$field]->setValue($entity, $proxy); $newData[$field] = $proxy; $this->_em->getUnitOfWork()->registerManaged($proxy, $joinColumnValues, array()); } } } } else { // Inverse side of 1-1/1-x can never be lazy. //$newData[$field] = $assoc->load($entity, null, $this->_em); $newData[$field] = $this->_em->getUnitOfWork()->getEntityPersister($assoc['targetEntity'])->loadOneToOneEntity($assoc, $entity, null); } } else { if ($value instanceof PersistentCollection && $value->isInitialized()) { $value->setInitialized(false); $newData[$field] = $value; } } } $this->_em->getUnitOfWork()->setOriginalEntityData($entity, $newData); }
/** * @return \Doctrine\ORM\Proxy\ProxyFactory */ public function getProxyFactory() { return isset($this->_proxyFactoryMock) ? $this->_proxyFactoryMock : parent::getProxyFactory(); }
/** * Compiles the Doctrine proxy class code using the Doctrine ProxyFactory. * * @return void */ public function compileProxies() { $proxyFactory = $this->entityManager->getProxyFactory(); $proxyFactory->generateProxyClasses($this->entityManager->getMetadataFactory()->getAllMetadata()); }
/** * INTERNAL: * Creates an entity. Used for reconstitution of persistent entities. * * @ignore * @param string $className The name of the entity class. * @param array $data The data for the entity. * @param array $hints Any hints to account for during reconstitution/lookup of the entity. * @return object The managed entity instance. * @internal Highly performance-sensitive method. * * @todo Rename: getOrCreateEntity */ 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) { if (isset($class->associationMappings[$fieldName])) { $id[$fieldName] = $data[$class->associationMappings[$fieldName]['joinColumns'][0]['name']]; } else { $id[$fieldName] = $data[$fieldName]; } } $idHash = implode(' ', $id); } else { if (isset($class->associationMappings[$class->identifier[0]])) { $idHash = $data[$class->associationMappings[$class->identifier[0]]['joinColumns'][0]['name']]; } 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; if ($entity instanceof NotifyPropertyChanged) { $entity->addPropertyChangedListener($this); } } else { $overrideLocalValues = isset($hints[Query::HINT_REFRESH]); // If only a specific entity is set to refresh, check that it's the one if (isset($hints[Query::HINT_REFRESH_ENTITY])) { $overrideLocalValues = $hints[Query::HINT_REFRESH_ENTITY] === $entity; } } if ($overrideLocalValues) { $this->originalEntityData[$oid] = $data; } } 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); } } // Loading the entity right here, if its in the eager loading map get rid of it there. unset($this->eagerLoadingEntities[$class->rootEntityName][$idHash]); // 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['fetchAlias']) && isset($hints['fetched'][$hints['fetchAlias']][$field])) { continue; } $targetClass = $this->em->getClassMetadata($assoc['targetEntity']); if ($assoc['type'] & ClassMetadata::TO_ONE) { if ($assoc['isOwningSide']) { $associatedId = array(); // TODO: Is this even computed right in all cases of composite keys? foreach ($assoc['targetToSourceKeyColumns'] as $targetColumn => $srcColumn) { $joinColumnValue = isset($data[$srcColumn]) ? $data[$srcColumn] : null; if ($joinColumnValue !== null) { if ($targetClass->containsForeignIdentifier) { $associatedId[$targetClass->getFieldForColumn($targetColumn)] = $joinColumnValue; } else { $associatedId[$targetClass->fieldNames[$targetColumn]] = $joinColumnValue; } } } if (!$associatedId) { // Foreign key is NULL $class->reflFields[$field]->setValue($entity, null); $this->originalEntityData[$oid][$field] = null; } else { if (!isset($hints['fetchMode'][$class->name][$field])) { $hints['fetchMode'][$class->name][$field] = $assoc['fetch']; } // 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]; // if this is an uninitialized proxy, we are deferring eager loads, // this association is marked as eager fetch, and its an uninitialized proxy (wtf!) // then we cann append this entity for eager loading! if ($hints['fetchMode'][$class->name][$field] == ClassMetadata::FETCH_EAGER && isset($hints['deferEagerLoad']) && !$targetClass->isIdentifierComposite && $newValue instanceof Proxy && $newValue->__isInitialized__ === false) { $this->eagerLoadingEntities[$targetClass->rootEntityName][$relatedIdHash] = current($associatedId); } } else { if ($targetClass->subClasses) { // If it might be a subtype, it can not be lazy. There isn't even // a way to solve this with deferred eager loading, which means putting // an entity with subclasses at a *-to-one location is really bad! (performance-wise) $newValue = $this->getEntityPersister($assoc['targetEntity'])->loadOneToOneEntity($assoc, $entity, $associatedId); } else { // Deferred eager load only works for single identifier classes if ($hints['fetchMode'][$class->name][$field] == ClassMetadata::FETCH_EAGER) { if (isset($hints['deferEagerLoad']) && !$targetClass->isIdentifierComposite) { // TODO: Is there a faster approach? $this->eagerLoadingEntities[$targetClass->rootEntityName][$relatedIdHash] = current($associatedId); $newValue = $this->em->getProxyFactory()->getProxy($assoc['targetEntity'], $associatedId); } else { // TODO: This is very imperformant, ignore it? $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); if ($assoc['inversedBy'] && $assoc['type'] & ClassMetadata::ONE_TO_ONE) { $inverseAssoc = $targetClass->associationMappings[$assoc['inversedBy']]; $targetClass->reflFields[$inverseAssoc['fieldName']]->setValue($newValue, $entity); } } } else { // Inverse side of x-to-one can never be lazy $class->reflFields[$field]->setValue($entity, $this->getEntityPersister($assoc['targetEntity'])->loadOneToOneEntity($assoc, $entity)); } } 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_EAGER) { $this->loadCollection($pColl); $pColl->takeSnapshot(); } else { $pColl->setInitialized(false); } $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; }
/** * {@inheritDoc} * * @static */ public static function getProxyFactory() { return \Doctrine\ORM\EntityManager::getProxyFactory(); }
/** * Refreshes an entity. * * @param array $id The identifier of the entity as an associative array from column names to values. * @param object $entity The entity to refresh. */ public final function refresh(array $id, $entity) { $sql = $this->_getSelectEntitiesSql($id); $params = array_values($id); if ($this->_sqlLogger !== null) { $this->_sqlLogger->logSql($sql, $params); } $stmt = $this->_conn->prepare($sql); $stmt->execute($params); $result = $stmt->fetch(Connection::FETCH_ASSOC); $stmt->closeCursor(); $metaColumns = array(); $newData = array(); // Refresh simple state foreach ($result as $column => $value) { $column = isset($this->_resultColumnNames[$column]) ? $this->_resultColumnNames[$column] : $column; if (isset($this->_class->fieldNames[$column])) { $fieldName = $this->_class->fieldNames[$column]; $type = Type::getType($this->_class->fieldMappings[$fieldName]['type']); $newValue = $type->convertToPHPValue($value, $this->_platform); $this->_class->reflFields[$fieldName]->setValue($entity, $newValue); $newData[$fieldName] = $newValue; } else { $metaColumns[$column] = $value; } } // Refresh associations foreach ($this->_class->associationMappings as $field => $assoc) { $value = $this->_class->reflFields[$field]->getValue($entity); if ($assoc->isOneToOne()) { if ($value instanceof Proxy && !$value->__isInitialized__) { continue; // skip uninitialized proxies } if ($assoc->isOwningSide) { $joinColumnValues = array(); foreach ($assoc->targetToSourceKeyColumns as $targetColumn => $srcColumn) { if ($metaColumns[$srcColumn] !== null) { $joinColumnValues[$targetColumn] = $metaColumns[$srcColumn]; } } if (!$joinColumnValues && $value !== null) { $this->_class->reflFields[$field]->setValue($entity, null); $newData[$field] = null; } else { if ($value !== null) { // Check identity map first, if the entity is not there, // place a proxy in there instead. $targetClass = $this->_em->getClassMetadata($assoc->targetEntityName); if ($found = $this->_em->getUnitOfWork()->tryGetById($joinColumnValues, $targetClass->rootEntityName)) { $this->_class->reflFields[$field]->setValue($entity, $found); // Complete inverse side, if necessary. if (isset($targetClass->inverseMappings[$this->_class->name][$field])) { $inverseAssoc = $targetClass->inverseMappings[$this->_class->name][$field]; $targetClass->reflFields[$inverseAssoc->sourceFieldName]->setValue($found, $entity); } $newData[$field] = $found; } else { $proxy = $this->_em->getProxyFactory()->getProxy($assoc->targetEntityName, $joinColumnValues); $this->_class->reflFields[$field]->setValue($entity, $proxy); $newData[$field] = $proxy; $this->_em->getUnitOfWork()->addToIdentityMap($proxy); } } } } else { // Inverse side of 1-1/1-x can never be lazy. $newData[$field] = $assoc->load($entity, null, $this->_em); } } else { if ($value instanceof PersistentCollection && $value->isInitialized()) { $value->setInitialized(false); $newData[$field] = $value; } } } $this->_em->getUnitOfWork()->setOriginalEntityData($entity, $newData); }
/** * {@inheritdoc} */ public function getProxyFactory() { return $this->wrapped->getProxyFactory(); }