简体   繁体   English

Doctrine2 /将元素从集合移动到另一个集合

[英]Doctrine2 / Move element from a Collection to another

I have 3 entities : Invoice , Service and Line 我有3个实体: InvoiceServiceLine

  • Invoice contains collection of Service Invoice包含Service集合
  • Service contains collection of Line Service包含Line集合

I want to move one Line from a Service collection to another Service collection but on flush, the Line element that I try to move is deleted from the database ... 我想一个移动LineService收集到另一个Service集合,但在冲洗时, Line ,我尝试移动元素是从数据库中删除...

Unit tests are OK without persist / flush 单位测试没有持久/冲洗即可

Example of usage : 用法示例:

if ($transferService)
{
    $line->transferToService($service1, $service2);
}
else
{
    $line->setService($service2);
}

Invoice : 发票:

class Invoice
{
    /**
     * @ORM\OneToMany(targetEntity="Service", mappedBy="invoice", cascade={"persist", "merge", "remove"}, orphanRemoval=true)
     */
    protected $services;

    // ...

    public function __construct()
    {
        $this->services = new ArrayCollection();
    }

    #################################################
    # SERVICES Array Collection handling            #
    #################################################

    public function getServices()
    {
        return $this->services;
    }

    public function setServices($services)
    {
        $this->services = new ArrayCollection();

        return $this->addServices($services);
    }

    public function addService(Service $service)
    {
        if (!$this->services->contains($service))
        {
            $this->services->add($service);
            $service->setInvoice($this);
        }

        return $this;
    }

    public function addServices($services)
    {
        foreach ($services as $service)
        {
            $this->addService($service);
        }

        return $this;
    }

    public function removeService(Service $service)
    {
        if ($this->services->contains($service))
        {
            $this->services->removeElement($service);
        }

        return $this;
    }

    public function removeServices($services)
    {
        foreach ($services as $service)
        {
            $this->removeService($service);
        }

        return $this;
    }        

    // ...
}

Service : 服务:

class Service
{
    /**
     * @ORM\OneToMany(targetEntity="Line", mappedBy="service", cascade={"persist", "remove", "merge"}, orphanRemoval=true)
     */
    protected $lines;

    /**
     * @ORM\ManyToOne(targetEntity="Invoice", inversedBy="services", cascade={"persist", "merge"})
     * @ORM\JoinColumn(name="invoice_id", referencedColumnName="id", onDelete="CASCADE")
     */
    protected $invoice;

    // ...

    public function __construct()
    {
        $this->lines = new ArrayCollection();
    }

    public function getInvoice()
    {
        return $this->invoice;
    }

    public function setInvoice(Invoice $invoice)
    {
        $this->invoice = $invoice;
        $invoice->addService($this);

        return $this;
    }

    #################################################
    # LINES Array Collection handling               #
    #################################################

    public function setLines($lines)
    {
        $this->lines = new ArrayCollection();

        return $this->addLines($lines);
    }

    public function getLines()
    {
        return $this->lines;
    }

    public function addLine(Line $line)
    {
        if (!$this->lines->contains($line))
        {
            $this->lines->add($line);
            $line->setService($this);
        }

        return $this;
    }

    public function addLines($lines)
    {
        foreach ($lines as $line)
        {
            $this->addLine($line);
        }

        return $this;
    }

    public function removeLine(Line $line)
    {
        if ($this->lines->contains($line))
        {
            $this->lines->removeElement($line);
        }

        return $this;
    }

    public function removeLines($lines)
    {
        foreach ($lines as $line)
        {
            $this->removeLine($line);
        }

        return $this;
    }

    // ...
}

Line : 线:

class Line
{
    /**
     * @ORM\ManyToOne(targetEntity="Service", inversedBy="lines", cascade={"persist", "merge"})
     * @ORM\JoinColumn(name="service_id", referencedColumnName="id", onDelete="CASCADE")
     */
    protected $service;

    public function setService(Service $service)
    {
        $this->service = $service;
        $service->addLine($this);

        return $this;
    }

    public function transferToService(Service $serviceFrom, Service $serviceTo)
    {
        $this->setService($serviceTo);
        $serviceFrom->removeLine($this);

        return $this;
    }

    public function getService()
    {
        return $this->service;
    }

    // ...

}

This is due to orphanRemoval={true} . 这是由于orphanRemoval={true} That means that collection object is privately owned only from "original" owner (eg: Line ). 这意味着集合对象仅由“原始”所有者私有 (例如: Line )。 see here 看这里

Your code seems to work well unless - and maybe you didn't noticed - original elements are gone but they are also created again with different ids. 您的代码似乎运行良好,除非 - 也许您没有注意到 - 原始元素已经消失,但它们也会使用不同的ID再次创建。 Please check this situation as I've experienced the same more than once. 请检查这种情况,因为我经历了不止一次。

So, if you want to keep the same object, you should remove orphanRemoval and handle yourself, by hand, collection lifetime (including removing; I bet you're using this to write less code as possible in form collection and embedded forms) 因此,如果你想保留相同的对象,你应该删除orphanRemoval并手动处理自己的收集生命周期(包括删除;我打赌你用它来在表单集和嵌入表单中尽可能少写代码)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM