Объект Persist с двумя иностранными идентичностями в доктрине

Я создал объект, использующий yml-синтаксис в моем наборе symfony, в папке Resources / config / doctrine:

Sulu\Bundle\TranslateBundle\Entity\Translation: type: entity table: tr_translations id: code: type: string column: idCodes associationKey: id catalogue: type: string column: idCatalogues associationKey: id fields: value: type: text manyToOne: code: targetEntity: Code inversedBy: tr_codes joinColumn: name: idCodes referencedColumnName: id catalogue: targetEntity: Catalogue inversedBy: tr_catalogues joinColumn: name: idCatalogues referencedColumnName: id 

Эта часть работает правильно. Но когда я создаю некоторые объекты, как в следующем коде, я получаю сообщение об ошибке, которое я должен использовать метод flush, чтобы получить идентификаторы для внешних ключей.

Это фрагмент кода, который я использую в настоящее время:

  // create a new package and catalogue for the import $package = new Package(); $package->setName($this->getName()); $catalogue = new Catalogue(); $catalogue->setLocale($this->getLocale()); $catalogue->setPackage($package); $this->em->persist($package); $this->em->persist($catalogue); // load the file, and create a new code/translation combination for every message $fileCatalogue = $loader->load($this->getFile(), $this->getLocale()); foreach ($fileCatalogue->all()['messages'] as $key => $message) { $code = new Code(); $code->setPackage($package); $code->setCode($key); $code->setBackend(true); $code->setFrontend(true); $translate = new Translation(); $translate->setCode($code); $translate->setValue($message); $translate->setCatalogue($catalogue); $this->em->persist($code); $this->em->flush(); //FIXME no flush in between, if possible $this->em->persist($translate); } // save all the changes to the database $this->em->flush(); Заказ  // create a new package and catalogue for the import $package = new Package(); $package->setName($this->getName()); $catalogue = new Catalogue(); $catalogue->setLocale($this->getLocale()); $catalogue->setPackage($package); $this->em->persist($package); $this->em->persist($catalogue); // load the file, and create a new code/translation combination for every message $fileCatalogue = $loader->load($this->getFile(), $this->getLocale()); foreach ($fileCatalogue->all()['messages'] as $key => $message) { $code = new Code(); $code->setPackage($package); $code->setCode($key); $code->setBackend(true); $code->setFrontend(true); $translate = new Translation(); $translate->setCode($code); $translate->setValue($message); $translate->setCatalogue($catalogue); $this->em->persist($code); $this->em->flush(); //FIXME no flush in between, if possible $this->em->persist($translate); } // save all the changes to the database $this->em->flush(); Заказ  // create a new package and catalogue for the import $package = new Package(); $package->setName($this->getName()); $catalogue = new Catalogue(); $catalogue->setLocale($this->getLocale()); $catalogue->setPackage($package); $this->em->persist($package); $this->em->persist($catalogue); // load the file, and create a new code/translation combination for every message $fileCatalogue = $loader->load($this->getFile(), $this->getLocale()); foreach ($fileCatalogue->all()['messages'] as $key => $message) { $code = new Code(); $code->setPackage($package); $code->setCode($key); $code->setBackend(true); $code->setFrontend(true); $translate = new Translation(); $translate->setCode($code); $translate->setValue($message); $translate->setCatalogue($catalogue); $this->em->persist($code); $this->em->flush(); //FIXME no flush in between, if possible $this->em->persist($translate); } // save all the changes to the database $this->em->flush(); 

Если я не вызываю флеш в цикле foreach, я получаю следующую ошибку, которую я полностью понимаю, но разве нет более элегантного решения этой проблемы?

Doctrine \ ORM \ ORMException: Сущность типа Sulu \ Bundle \ TranslateBundle \ Entity \ Translation имеет личность через внешний объект Sulu \ Bundle \ TranslateBundle \ Entity \ Code, однако этот объект не имеет самоидентификации. Вы должны вызвать EntityManager # persist () для связанного объекта и убедиться, что был создан идентификатор, прежде чем пытаться сохранить «Sulu \ Bundle \ TranslateBundle \ Entity \ Translation». В случае создания Post Insert ID Generation (например, MySQL Auto-Increment или PostgreSQL SERIAL) это означает, что вы должны вызывать EntityManager # flush () между обеими персистентными операциями.

Related of "Объект Persist с двумя иностранными идентичностями в доктрине"

К сожалению, согласно Doctrine Docs вам нужно вызвать flush, чтобы получить идентификаторы для ваших внешних ключей:

Сгенерированные идентификаторы сущностей / первичные ключи гарантированно будут доступны после следующей успешной операции флеша, которая включает соответствующий объект. Вы не можете полагаться на сгенерированный идентификатор, который будет доступен сразу после вызова persist. Обратное также верно. Вы не можете полагаться на сгенерированный идентификатор, недоступный после неудачной операции сброса.

Вы пробовали что-то вроде следующего?

YAML:

 Sulu\Bundle\TranslateBundle\Entity\Translation: type: entity table: tr_translations id: code: type: string column: idCodes associationKey: id catalogue: type: string column: idCatalogues associationKey: id fields: value: type: text manyToOne: code: targetEntity: Code cascade: ["persist"] inversedBy: tr_codes joinColumn: name: idCodes referencedColumnName: id catalogue: targetEntity: Catalogue cascade: ["persist"] inversedBy: tr_catalogues joinColumn: name: idCatalogues referencedColumnName: id 

В вашем классе Перевод

 public function __construct() { $this->code = new \Doctrine\Common\Collections\ArrayCollection(); $this->catalogue = new \Doctrine\Common\Collections\ArrayCollection(); } public function addCatalogue($catalogue) { $this->catalogue[] = $catalogue; return $this; } public function addCode($code) { $this->code[] = $code; return $this; } 

Тогда ваш код может выглядеть примерно так:

 $package = new Package(); $package->setName($this->getName()); $catalogue = new Catalogue(); $catalogue->setLocale($this->getLocale())->setPackage($package); $fileCatalogue = $loader->load($this->getFile(), $this->getLocale()); foreach ($fileCatalogue->all()['messages'] as $key => $message) { $code = new Code(); $code->setPackage($package) ->setCode($key) ->setBackend(true) ->setFrontend(true); $translate = new Translation(); $translate->addCode($code) ->setValue($message) ->addCatalogue($catalogue); $this->em->persist($translate); } $this->em->flush(); Заказ $package = new Package(); $package->setName($this->getName()); $catalogue = new Catalogue(); $catalogue->setLocale($this->getLocale())->setPackage($package); $fileCatalogue = $loader->load($this->getFile(), $this->getLocale()); foreach ($fileCatalogue->all()['messages'] as $key => $message) { $code = new Code(); $code->setPackage($package) ->setCode($key) ->setBackend(true) ->setFrontend(true); $translate = new Translation(); $translate->addCode($code) ->setValue($message) ->addCatalogue($catalogue); $this->em->persist($translate); } $this->em->flush(); 

Примечание: cascade: ["persist"] – Cascades сохраняют операции со связанными объектами. Ссылка