Я пытаюсь сохранить Entity, который может или не может существовать и может иметь или не иметь одно или два отношения (код ниже). Мой текущий метод приводит к ошибкам, я вполне уверен, что могу придумать некоторые обходные пути/хаки самостоятельно, но меня интересует правильный "официальный" способ сделать это.
Что я сейчас пытаюсь сделать:
$entity = new myEntity();
if ( !empty($id) )
{
$entity->setId($id);
}
$entity->setLocationId($relation_id); //may or may not be null, if not null it always an already existing location entry in a different table, i.e. not a new
$entity = $entity_manager->merge($entity);
$entity_manager->flush();
В настоящее время Doctrine жалуется на то, что Location является новым Entity без идентификатора, и политика не позволяет автоматически генерировать идентификаторы. Политика действительно такова, но я вообще не добавляю объект местоположения, я использую метод setLocationId(), созданный автоматически, который добавляет точно существующий идентификатор местоположения, поэтому я немного озадачен.
edit: Я получаю ошибку doctrine, когда идентификатор местоположения не является нулевым, а реальным, существующим (в db) идентификатором местоположения.
И модель:
Location:
type: entity
table: locationstable
id:
my-id-column:
type: string
fields:
some fields
oneToMany:
myEntities:
targetEntity: myEntity
mappedBy: location
cascade: ["persist", "merge"]
Если вы собираетесь использовать Doctrine 2 ORM, вам действительно нужно использовать его, как было разработано. Это означает работу с объектами, а не с идентификаторами. Если вам не нравится этот подход, переключитесь на какую-то активную реализацию записи.
//For your case, start by seeing if there is an existing entity:
// This eliminates all the merge nonsense
$entity = $entityManager->getRepository('EntityClassName')->find($entityId);
if (!$entity)
{
$entity = new Entity();
/* Only do this is you are not autogenerating id's
* However, it does raise the question of how you know what the id should be if the entity
* if the entity does not yet exist?
*/
$entity->setId($id);
// Persist the new entity
$entityManager->persist($entity);
}
// Now get a reference to the location object which saves loading the entire location
// which optimizes things a tiny (probably unnoticeable) bit
$location = $entityManager->getReference('LocationClassName',$locationId);
$entity->setLocation($location);
// And flush changes
$entityManager->flush();
И снова, если вы считаете, что это слишком сложно или слишком много запросов, тогда не используйте Doctrine 2. Вы будете бороться с ним постоянно. На практике Doctrine 2 получается неплохо. Никакой реальной необходимости беспокоиться о микро-оптимизации.
Попробуйте найти запись местоположения и добавить к объекту:
$entity = new myEntity();
if ( !empty($id) )
{
$entity->setId($id);
}
//$entity->setLocationId($relation_id); //may or may not be null, if not null it always an already existing
$location = $locationRepository->find($relation_id);
$entity->setLocation($location);
location entry in a different table, i.e. not a new
$entity = $entity_manager->merge($entity);
$entity_manager->flush();
cascade
операции может быть дороже: посмотрите на этот документ . Кстати, мой выбор - поиск по идентификатору таблицы, это не займет больше времени