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

时间:2016-05-31 09:13:23

标签: php symfony doctrine-orm zend-framework2

我有3个实体:InvoiceServiceLine

  • Invoice包含Service
  • 的集合
  • Service包含Line
  • 的集合

我想将LineService集合移动到另一个Service集合,但在flush上,我尝试移动的Line元素将从数据库中删除...

单位测试没有持久/冲洗

使用示例:

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

发票:

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;
    }        

    // ...
}

服务:

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;
    }

    // ...
}

行:

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;
    }

    // ...

}

1 个答案:

答案 0 :(得分:3)

这是由于orphanRemoval={true}。这意味着集合对象私有仅由" original"所有者(例如:Line)。 see here

您的代码似乎运行良好,除非 - 也许您没有注意到 - 原始元素已经消失,但它们也会使用不同的ID再次创建。请检查这种情况,因为我经历了不止一次。

所以,如果你想保留相同的对象,你应该删除orphanRemoval并手动处理自己的收集生命周期(包括删除;我打赌你用它来尽可能少写代码在表单集和嵌入表单中)