具有学说 2 中附加字段的双向自引用映射


Bidirectional self-referencing mapping with additional fields in doctrine 2

我被困在这个上面。这是我得到的:

我得到了一个Document的Entitiy,它能够拥有$previosDocuments$nextDocuments。这种关系是bidirectional的,它们都是ArrayCollections的。但我还需要了解一些其他附加信息。这就是为什么我得到了一个包含附加字段的DocumentRelation实体。

注意:我知道下面的代码根本不正确。

这是我到目前为止的代码:

/**
 * @ORM'Entity
 * @ORM'Table(name="document")
 */
class Document
{
    /**
     * @var integer
     *
     * @ORM'Column(name="id", type="integer")
     * @ORM'Id
     * @ORM'GeneratedValue(strategy="AUTO")
     */
    protected $id;
    /**
     * @var string $name
     * @ORM'Column(type="string")
     */
    protected $name;
    /**
     * @var ArrayCollection $nextDocuments
     * @ORM'OneToMany(targetEntity="App'FrontEndBundle'Entity'DocumentRelation", mappedBy="document", cascade={"persist"})
     */
    protected $nextDocuments;
    /**
     * @var ArrayCollection $prevDocuments
     * @ORM'OneToMany(targetEntity="App'FrontEndBundle'Entity'DocumentRelation", mappedBy="targetDocument", cascade={"persist"})
     */
    protected $prevDocuments;
    /**
     * Document constructor.
     */
    public function __construct()
    {
        $this->prevDocuments = new ArrayCollection();
        $this->nextDocuments = new ArrayCollection();
    }
    /**
     * @param Document $nextDocument
     * @return $this
     */
    public function removeNextDocument($nextDocument)
    {
        if ($this->nextDocuments->contains($nextDocument)) {
            $this->nextDocuments->removeElement($nextDocument);
            $nextDocument->removePrevDocument($this);
        }
        return $this;
    }
    /**
     * @param Document $nextDocument
     * @return $this
     */
    public function addNextDocument($nextDocument)
    {
        if (!$this->nextDocuments->contains($nextDocument)) {
            $this->nextDocuments->add($nextDocument);
            $nextDocument->addPrevDocument($this);
        }
        return $this;
    }
    /**
     * @param Document $prevDocument
     * @return $this
     */
    public function addPrevDocument($prevDocument)
    {
        if (!$this->prevDocuments->contains($prevDocument)) {
            $this->prevDocuments->add($prevDocument);
            $prevDocument->addNextDocument($this);
        }
        return $this;
    }
    /**
     * @param Document $prevDocument
     * @return $this
     */
    public function removePrevDocument($prevDocument)
    {
        if ($this->prevDocuments->contains($prevDocument)) {
            $this->prevDocuments->removeElement($prevDocument);
            $prevDocument->removeNextDocument($this);
        }
        return $this;
    }
    //getter + setter 
}
/**
 * Class DocumentRelation
 * @package App'FrontEndBundle'Entity
 * @ORM'Entity
 * @ORM'Table(name="document_relation")
 */
class DocumentRelation
{
    /**
     * @var Document $targetDocument
     * @ORM'ManyToOne(targetEntity="App'FrontEndBundle'Entity'Document", inversedBy="id")
     * @ORM'JoinColumn(name="target_document_id", referencedColumnName="id")
     */
    protected $targetDocument;
    /**
     * @var Document $document
     * @ORM'ManyToOne(targetEntity="App'FrontEndBundle'Entity'Document", inversedBy="id")
     * @ORM'JoinColumn(name="document_id", referencedColumnName="id")
     */
    protected $document;
    [...] //$id & getter + setter 
}

我的问题是,我不知道如何让它们一起工作。对于任何想法,帮助或提示,我将不胜感激!

编辑:我想要的结尾是一个具有双向关联的自引用实体和一些额外的字段来保存有关双向关系的一些附加信息。

编辑 2 @Kuba-Birecki:

public function indexAction()
{
   $this->createDocuments();
   return $this->render('AppFrontEndBundle:Default:index.html.twig');
}
private function createDocuments()
{
    $firstDocument = (new Document())->setName('first');
    $secondDocument = (new Document())->setName('second');
    $firstDocument->addNextDocument($secondDocument);
    $em = $this->getDoctrine()->getManager();
    $em->persist($firstDocument);
    $em->flush();
}

这是我尝试持久化它的方式,这也是我需要调用它的方式。

例外是波纹管

在关联应用程序''前端捆绑包''实体''文档上

找到类型为"应用程序"''"前端捆绑包"''"实体''文档#nextDocuments"的实体,但需要应用''前端捆绑包''实体''文档关系

您的注释看起来没问题,但您的业务逻辑不反映这些规则。

Document类的$nextDocuments应该包含DocumentRelation的集合,但是在您的方法中,您尝试在其中插入Document对象。$prevDocuments也是如此。

您只需要更改Document类即可使用DocumentRelation对象而不是Document

class Document
{
    ...
    /**
     * @param DocumentRelation $relation
     * @return $this
     */
    public function removeNextDocument(DocumentRelation $relation)
    {
        if ($this->nextDocuments->contains($relation)) {
            $this->nextDocuments->removeElement($relation);
            $relation->setDocument(null);
        }
        return $this;
    }
    /**
     * @param DocumentRelation $relation
     * @return $this
     */
    public function addNextDocument(DocumentRelation $relation)
    {
        if (!$this->nextDocuments->contains($relation)) {
            $this->nextDocuments->add($relation);
            $relation->setDocument($this);
        }
        return $this;
    }
    /**
     * @param DocumentRelation $relation
     * @return $this
     */
    public function addPrevDocument(DocumentRelation $relation)
    {
        if (!$this->prevDocuments->contains($relation)) {
            $this->prevDocuments->add($relation);
            $relation->setTargetDocument($this);
        }
        return $this;
    }
    /**
     * @param DocumentRelation $relation
     * @return $this
     */
    public function removePrevDocument(DocumentRelation $relation)
    {
        if ($this->prevDocuments->contains($relation)) {
            $this->prevDocuments->removeElement($relation);
            $relation->setTargetDocument(null);
        }
        return $this;
    }
}

当然,这也意味着您必须在将这些DocumentRelation对象传递给这些方法之前创建/获取它们。

然后,例如,如果您想通过直接传递而不是DocumentRelation来检查$prevDocuments是否包含某个Document,您可以这样做:

public function hasPrevDocument(Document $document)
{
    // Iterate over DocumentRelations
    foreach ($this->prevDocuments as $relation) {
        // Check if the relation refers to the wanted document
        if ($relation->getDocument() === $document) {
            return true;
        }
    }
    return false;
}

我希望这有所帮助。