Как ManyToMany и OneToMany в Symfony и Doctrine?

Я нахожу документацию очень плохой, когда дело доходит до объяснения создания отношений между сущностями. Так что мне придется обратиться за помощью к моим коллегам StackExchangers. Итак, я пытаюсь построить следующие случаи:

корпус 1

A User принадлежит одному или нескольким Group и Group может быть много Permission. А User также может иметь Permission.

корпус 2

A Ticket есть Category, несколько Tag и несколько Comment.

спасибо заранее!

2 ответов


конечно. Первое, что нужно понять, - это то, что нет "одного способа" сделать это. Доктрина дает много гибкости с точки зрения того, как вы определить отношение - даже если несколько определений производят один и тот же DDL (и это важно понять - некоторые из вариантов отображения влияют только на объектную сторону ORM, а не на модельную сторону)

вот пример ваших пользователей / групп / разрешений, которые на самом деле являются ассоциациями "многие ко многим" (я исключил все несущественный, но необходимый код, например определение столбца PK)

<?php

namespace Your\Bundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * @ORM\Entity
 */
class User
{
  /**
   * Many-To-Many, Unidirectional
   *
   * @var ArrayCollection $groups
   *
   * @ORM\ManyToMany(targetEntity="Group")
   * @ORM\JoinTable(name="user_has_group",
   *      joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
   *      inverseJoinColumns={@ORM\JoinColumn(name="group_id", referencedColumnName="id")}
   * )
   */
  protected $groups;

  /**
   * Many-To-Many, Unidirectional
   *
   * @var ArrayCollection $permissions
   *
   * @ORM\ManyToMany(targetEntity="Permission")
   * @ORM\JoinTable(name="user_has_permission",
   *      joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
   *      inverseJoinColumns={@ORM\JoinColumn(name="permission_id", referencedColumnName="id")}
   * )
   */
  protected $permissions;

  public function __construct()
  {
    $this->groups = new ArrayCollection();
    $this->permissions = new ArrayCollection();
  }
}

/**
 * @ORM\Entity
 */
class Group
{
  /**
   * Many-To-Many, Unidirectional
   *
   * @var ArrayCollection $permissions
   *
   * @ORM\ManyToMany(targetEntity="Permission")
   * @ORM\JoinTable(name="group_has_permission",
   *      joinColumns={@ORM\JoinColumn(name="group_id", referencedColumnName="id")},
   *      inverseJoinColumns={@ORM\JoinColumn(name="permission_id", referencedColumnName="id")}
   * )
   */
  protected $permissions;

  public function __construct()
  {
    $this->permissions = new ArrayCollection();
  }
}

/**
 * @ORM\Entity
 */
class Permission {}

Если у вас есть вопросы о том, что происходит здесь, дайте мне знать.

теперь, ко второму примеру

<?php

namespace Your\Bundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * @ORM\Entity
 */
class Ticket
{
  /**
   * Many-To-One, Unidirectional
   *
   * @var Category
   *
   * @ORM\ManyToOne(targetEntity="Category")
   * @ORM\JoinColumn(name="category_id", referencedColumnName="id")
   */
  protected $category;

  /**
   * Many-To-Many, Unidirectional
   *
   * @var ArrayCollection $permissions
   *
   * @ORM\ManyToMany(targetEntity="Tag")
   * @ORM\JoinTable(name="tickt_has_tag",
   *      joinColumns={@ORM\JoinColumn(name="ticket_id", referencedColumnName="id")},
   *      inverseJoinColumns={@ORM\JoinColumn(name="tag_id", referencedColumnName="id")}
   * )
   */
  protected $tags;

  /**
   * One-To-Many, Bidirectional
   *
   * @var ArrayCollection $comments
   *
   * @ORM\OneToMany(targetEntity="Comment", mappedBy="ticket")
   */
  protected $comments;

  public function __construct()
  {
    $this->tags = new ArrayCollection();
    $this->comments = new ArrayCollection();
  }
}

/**
 * @ORM\Entity
 */
class Comment
{
  /**
   * Many-To-One, Bidirectional
   *
   * @var Ticket $ticket
   *
   * @ORM\ManyToOne(targetEntity="Ticket")
   * @ORM\JoinColumn(name="ticket_id", referencedColumnName="id")
   */
  protected $ticket=null;
}

/**
 * @ORM\Entity
 */
class Tag {}

/**
 * @ORM\Entity
 */
class Category {}

Как и раньше, дайте мне знать, если вы хотели, чтобы все это объяснить.

P.S. На самом деле ничего из этого не было протестировано, я просто быстро ударил его в своей IDE. Может быть опечатка или две ;)


попробуйте это:

Class User {  
 /**
  * @ORM\OneToMany(targetEntity="path\to\group", mappedBy="user", cascade={"persist", "remove"})
  */
  private $group;

у вас будет одно ко многим отношениям между User и Group.. The targetEntity - это путь к сущности, которую вы хотите иметь отношения с mappedBy является переменной из Group сущности. cascade означает User добавить в Group и удалить из Group

Группа Класс {

/**
 * @ORM\ManyToOne(targetEntity="path\to\user, inversedBy="group")
 * @ORM\JoinColumn(name="user_id", referencedColumnName="id")
 */
private $user;

это резервная сторона отношений.. targetEntity должен иметь путь обратно к родительской сущности, которая User в этом случае. inversedBy является переменной из User сущности. JoinColumn просто говорит доктрине, что присоединиться, это автоматически делается, если вы не установите его самостоятельно.