Двунаправленное самореферентное отображение с дополнительными полями в доктрине 2

Я застрял на этом. Вот что я получил:

Я получил DocumentEntitiy, который может иметь $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 @ Куба-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();
}

Это способ, которым я пытаюсь сохранить это, и это также, как я должен назвать это.

Исключение ниже

Найденная сущность типа App \ FrontEndBundle \ Entity \ Document в ассоциации App \ FrontEndBundle \ Entity \ Document # nextDocuments, но ожидающая App \ FrontEndBundle \ Entity \ DocumentRelation

2

Решение

Ваши аннотации выглядят хорошо, но ваша бизнес-логика не отражает эти правила.

$nextDocuments из Document класс должен содержать коллекцию 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 объекты перед передачей их этим методам.

Затем, если, например, вы хотите проверить, $prevDocuments содержит определенный Document передавая его непосредственно вместо DocumentRelation, вы бы сделали это так:

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

Надеюсь, это поможет.

0

Другие решения

Других решений пока нет …