Doctrine XOR实体上的两个关系

时间:2017-07-11 14:07:02

标签: symfony doctrine-orm doctrine

给定一个实体A,它通过可选 ManyToOne关系与实体BC相关联 - 这是确保最佳方式的最佳方式一次只使用其中一个关系(XOR)?

我想要实现的目标很好地说明了下面的图像(基数在那里显示不同):

enter image description here

当然,我可以确保引用在存储库代码或其他地方有效,但也许有更多"正确的"使用Doctrine映射功能的方法吗?

A

/**
 * @ORM\Table(name="A")
 * @ORM\Entity(repositoryClass="Test\AppBundle\Repository\ARepository")
 */
class A
{
    /**
     * @var
     * @ORM\ManyToOne(targetEntity="B", inversedBy="as", cascade={"all"})
     */
    private $b = null;

    /**
     * @var null
     * @ORM\ManyToOne(targetEntity="C", inversedBy="as", cascade={"all"}))
     */
    private $c = null;
}

/**
 * @ORM\Table(name="B")
 * @ORM\Entity(repositoryClass="Test\AppBundle\Repository\BRepository")
 */
class B
{
    /**
     * @var
     * @ORM\OneToMany(targetEntity="A", mappedBy="b", cascade={"all"})
     */
    private $as = null;
}

C

/**
 * @ORM\Table(name="C")
 * @ORM\Entity(repositoryClass="Test\AppBundle\Repository\CRepository")
 */
class C
{
    /**
     * @var
     * @ORM\OneToMany(targetEntity="A", mappedBy="c", cascade={"all"})
     */
    private $as = null;
}

1 个答案:

答案 0 :(得分:1)

我不知道有一个内置的解决方案(并且没有最佳的教义实践),但这里有一些可能对你有帮助的想法:

<强> 1。使用getter / setter方法来&#34; null&#34; $ b关联,如果$ c设置,反之亦然

看起来像这样:

public function setB($b) {
    $this->b = $b;
    if($b !== null) {
        $this->c = null;
    }
}

优点是您的实体不可能具有设置$ b和$ c的无效状态。然而,学说使用反射,例如if实体实例是从持久对象创建的,以防止__construct调用。 可能是因为setter方法也有原因所以你的实体进入了一个不需要的状态,但是我不能把我的指控归为一类(可能是为了防止某种脏状态)。

此外,您可以将此视为副作用,对于A类的用户可能不需要(特别是在您不希望出现这种行为的简单setter方法中)。这是您必须在上下文中详细说明的内容。

这个解决方案可以使用symfony表单。只要属性不公开,表单系统will call the setter methods

  

除非财产是公开的,否则它必须有一个&#34; getter&#34;和&#34; setter&#34;方法,以便Form组件可以获取并将数据放到属性上。

<强> 2。使用生命周期回调

我会亲自尝试这种方法,因为我觉得它更容易理解。 (见documentation

使用prePersist的示例:

/**
* @ORM\PrePersist
* @ORM\PreUpdate
*/
public function checkAssociations()
{
    if($this->a !== null && $this->b !== null) {
        // throw some error
    }
}

此代码

  • 更好的可读性(imo),因为它更像&#34;明文一样&#34; (&#34;如果a和b都设置,则抛出错误&#34; )而不是setter-solution
  • 不易出错(无法保证调用您的setter方法)

希望有所帮助。

如果有人对symfony中的setter调用有更多信息,那就太棒了。