Обычное отношение «многие ко многим» в доктрине - PullRequest
0 голосов
/ 29 марта 2019

Допустим, я хочу реализовать в Doctrine следующие сущности:

Thing представляет все, что может выполнить действие над другим Thing.Relation может содержать две сущности и описание действия, и его кортеж уникален.

Вот несколько примеров того, чего я пытаюсь достичь:

  • Hens(вещь) откладывать (действие) яйца (вещь)
  • Вода (вещь) гасит (действие) огонь (вещь)
  • Боб (вещь) любит (действие) яблоки (вещь)
  • Боб (вещь) пьет (действие) воду (вещь)

Как видите, порядок имеет значение (это не то же самое, что "Боб любит яблоки", чем "Яблоки, как Боб").


Несмотря на все мои усилия, я не могу найти какой-либо правильный способ реализовать это.

Я пытался создать поле с именем $relations в Thing с тегом "One-To-Many ", а затем пометить $left и $right в Relation как" Many-To-One ".Проблема в том, что у меня не может быть двух перевернутых сторон для одной и той же стороны-владельца (по крайней мере, AFAIK).

Эта текущая реализация также не позволяет получить все отношения для определенного Thing в поле $relations какЯ могу указать только одну перевернутую сторону.

Вот что я придумал:

/** @ORM\Entity */
class Thing {
  /**
   * @ORM\Id
   * @ORM\Column(type="integer", options={"unsigned":true})
   * @ORM\GeneratedValue
   */
  protected $id;

  /** @ORM\Column(type="string") */
  protected $name;

  /**
   * @ORM\OneToMany(targetEntity="Relation", mappedBy="right")
   */
  protected $relations;
}


/** @ORM\Entity */
class Relation {
  /** @ORM\Id @ORM\Column(type="string") */
  protected $action;

  /** @ORM\Id @ORM\ManyToOne(targetEntity="Thing") */
  private $left;

  /** @ORM\Id @ORM\ManyToOne(targetEntity="Thing", inversedBy="relations") */
  private $right;
}

1 Ответ

0 голосов
/ 11 апреля 2019

Оказывается, доктрина напрямую не допускает такого рода отношений.

Лучшее решение, которое я мог придумать, - это создать две коллекции в Thing для отношений вместо одной, а затем определитьметод, который выводит оба:

/** @ORM\Entity */
class Thing {
  // [...]

  /** @ORM\OneToMany(targetEntity="Relation", mappedBy="left") */
  protected $relationsLeft;

  /** @ORM\OneToMany(targetEntity="Relation", mappedBy="right") */
  protected $relationsRight;

  public function getRelations() {
    return new ArrayCollection(array_merge(
      $this->relationsLeft->toArray(),
      $this->relationsRight->toArray()
    ));
  }
}


/** @ORM\Entity */
class Relation {
  // [...]

  /** @ORM\Id @ORM\ManyToOne(targetEntity="Thing", inversedBy="relationsLeft") */
  private $left;

  /** @ORM\Id @ORM\ManyToOne(targetEntity="Thing", inversedBy="relationsRight") */
  private $right;
}
...