在教义 - symfony中的OneToMany关系操作

时间:2016-09-23 08:18:56

标签: php symfony doctrine-orm

我不清楚如何处理OneToMany方面的操作。

让我们说对象A在ManyToOne一侧,而对象B在OneToMany一侧。

  1. 我想在创建一个对象B时,为它分配许多对象 - 我的解决方法是获取A对象并分配给它们 B对象

  2. 我想在删除对象B时,将所有对象的引用设置为null A - 从研究中我发现我可能需要添加一个ondelete="setNull" 表格上的功能

  3. 有没有更好的方法(或一般的替代方案)来处理这种情况?

2 个答案:

答案 0 :(得分:0)

use Doctrine\ORM\Mapping as ORM;

class AObject
{
    // ...

    /**
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\BObject", inversedBy="a", onDelete="SET NULL")
     */
    private $b;
}

class BObject
{
    // ...

    /**
     * @ORM\OneToMany(targetEntity="AppBundle\Entity\AObject", mappedBy="b", cascade={"persist"})
     */
    private $a;

    public function __construct()
    {
        $this->a = new \Doctrine\Common\Collections\ArrayCollection();
    }

    /**
     * @return \Doctrine\Common\Collections\ArrayCollection
     */
    public getA()
    {
        return $this->a;
    }

    /**
     * @param \Doctrine\Common\Collections\ArrayCollection $a
     */
    public setA($a)
    {
        $this->a = $a;
    }

    /**
     * @param AObject $a
     * @return BObject
     */
    public addA($a)
    {
        $this->a[] = $a;
        $a->setB($this); // assign B object to A

        return $this; // For method chaining
    }

    /**
     * @param AObject $a
     */
    public removeA($a)
    {
        $this->a->removeElement($a);
    }
}

对于1)你仍然需要获取你的对象,你的代码不能神奇地知道哪些A对象分配给你的新B对象。

使用上面定义的B类,你可以写

$b = new BObject();
$b
    ->addA($a1)
    ->addA($a2)
    ->addA(new AObject());
$entityManager->persist($b);
$entityManager->flush();

和A对象将引用B。

对于2)它是更好的解决方案,将其处理到数据库级别。

答案 1 :(得分:0)

出于您的目的,您可以使用doctrine lifecycle events

对于示例,首先需要定义事件侦听器:

# /src/FooBundle/Resources/config/services.yml
services:

# Event subscribers
foo.bar.subscriber:
    class: FooBundle\EventListener\BarSubscriber
    tags:
       - { name: doctrine.event_subscriber }

然后,创建一个:

// FooBundle\EventListener\BarSubscriber.php
namespace FooBundle\EventListener;

use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\LifecycleEventArgs;

class BarSubscriber implements EventSubscriber
{
    public function getSubscribedEvents()
    {
        return array(
            'preRemove',
            'postPersist',
        );
    }

    // This method will be executed on each entity, before it has been deleted
    // You can do here what u want in your second paragraph
    public function preRemove(LifecycleEventArgs $args) 
    {
        $entity = $args->getEntity();

        // Do not forget to check your entity type
        if (!$entity instanceof SomeInterface) {
            return;
        }

        // Some code that handle some actions on related entites
    }

    // This code will be executed after each entity creation
    // Here you can add more relations for your main entity
    public function postPersist(LifecycleEventArgs $args) 
    {
        $entity = $args->getEntity();
        if (!$entity instanceof TimestampableInterface) {
            return;
        }

        // Some actions on relations, after the establishment of the main object
    }
}

此外,作为替代方案,您可以使用Doctrine cascade operations删除所有儿童访问