在学说中坚持具有两个外国身份的对象

时间:2013-08-09 09:33:27

标签: php database symfony doctrine-orm

我在我的symfony包中使用yml-syntax创建了一个实体,位于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方法,以获取外键的ID。

这是我目前使用的代码段:

    // 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循环中调用flush,我会收到以下错误,我完全理解,但是对于这个问题,是不是有更优雅的解决方案?

  

Doctrine \ ORM \ ORMException:类型的实体   Sulu \ Bundle \ TranslateBundle \ Entity \ Translation有一个身份通过   外国实体Sulu \ Bundle \ TranslateBundle \ Entity \ Code,但是这个   实体本身没有身份。你必须打电话   EntityManager#persist()在相关实体上并确保一个   在尝试持久化之前生成了标识符   '苏鲁\包\ TranslateBundle \实体\翻译'。如果是邮政   插入ID生成(例如MySQL自动增量或PostgreSQL   SERIAL)这意味着你必须在两者之间调用EntityManager #flush()   坚持不懈的行动。

2 个答案:

答案 0 :(得分:4)

不幸的是,根据Doctrine Docs,您必须调用flush来获取外键的ID:

  

保证生成的实体标识符/主键   在下一次成功的冲洗操作之后可以使用   有问题的实体。您不能依赖生成的标识符   在调用persist后直接可用。反之亦然。   您不能依赖生成的标识符在a之后不可用   刷新操作失败。

答案 1 :(得分:0)

您是否尝试过以下内容?

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();

注意: cascade:[“persist”] - Cascades将操作持久保存到关联实体。 Link