如何让Doctrine 2忽略通过关系找到的新实体?

时间:2013-05-28 14:09:54

标签: php doctrine-orm

例如,我有以下两个类(为了简洁省略了getter / setter),它们在映射中都有两种方式链接:

class Form
{
    private $elements = array();

    public function addElement($element)
    {
        $this->elements[] = $element
        $element->setForm($this);
    }
}

class Element
{
    private $form;
    private $name;
}

<one-to-many field="elements" target-entity="Element" mapped-by="form"/>

<many-to-one field="form" target-entity="Form" inversed-by="elements">
    <join-column name="formId" referenced-column-name="id" on-delete="CASCADE" on-update="CASCADE"/>
</many-to-one>

如果我做以下事情;向表单添加两个元素,但只保留一个元素,我想要发生的是实体管理器完全忽略unistedisted元素,但另一个元素和要插入数据库的表单:

$form = new Form;
$em->persist($form);

$element = new Element;
$element->setName('firstName');
$form->addElement($element);
$em->persist($element);

$element2 = new Element;
$element2->setName('lastName');
$form->addElement($element2);

$em->flush();

目前收到以下错误:

exception 'Doctrine\ORM\ORMInvalidArgumentException' with message 'A new entity was found through the relationship 'Form#elements' that was not configured to cascade persist operations for entity Element@0000000019217f52000000009c20d747. To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example @ManyToOne(..,cascade={"persist"}). If you cannot find out which entity causes the problem implement 'Element#__toString()' to get a clue

据我所知,没有级联选项可以忽略新实体(http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/working-with-associations.html#transitive-persistence-cascade-operations)并使用preUpdate生命周期回调从$ elements数组中删除有问题的实体也不起作用,因为异常是在回调运行之前抛出。

这有什么办法吗?

2 个答案:

答案 0 :(得分:0)

尝试只冲洗你想要的实体:

$form = new Form;
$em->persist($form);
$em->flush($form);

$element = new Element;
$element->setName('firstName');
$form->addElement($element);
$em->persist($element);
$em->flush($element);

//ignored element
$element2 = new Element;
$element2->setName('lastName');
$form->addElement($element2);

答案 1 :(得分:0)

由于这是我能找到的唯一与此问题相关的页面,因此我将添加我自己提出的解决方案。 (在我的项目中,它基本上也是一个带有答案的表单,我在其中手动保存已更新的答案,但在保留表单时不应将不完整的答案保存到数据库中。)

基本上,您为关系创建两个属性:一个仅用于加载持久化的相关元素 ($subEntities),另一个将向公众提供 ($chachedSubEntities)。< /p>

$cachedSubEntities 成员将在您第一次调用 getSubEntities 时使用持久化的子实体进行初始化。

class MyEntity extends AbstractEntity
{
    /**
     * @ORM\OneToMany(targetEntity="SubEntity", mappedBy="parent", indexBy="id")
     */
    protected $subEntities;
    
    protected $cachedSubEntities;

    public function __construct()
    {
        $this->subEntities = new ArrayCollection();
    }
    
    public function getSubEntities()
    {
        if (is_null($this->cachedSubEntities)) {
            $this->cachedSubEntities = new ArrayCollection($this->subEntities->toArray());
        }
        return $this->cachedSubEntities;
    }
}