symfony Doctrine -- Cвязанные сущности -- Пример Many To Many связи (с использованием PersistentCollection)
Primary tabs
Здесь описан пример, как создать связь("друзей") в таблице User (Пользователи) -- Many To Many (многие ко многим), и в частности Self-referencing (связь данной таблицы с самой собой). Можно будет в контроллере достать всех пользователей - "друзей" данного пользователя.
Entity User
- Создаём аннотации для связи Many-To-Many в соответствии с документацией
- Свойства $friendsWithMe и $myFriends - объекты ArrayCollection. Это определяется в конструкторе класса. О том, кто такой ArrayCollection, для чего он нужен и с чем его едят, можно почитать здесь.
И для каждого поля методы:
addProp() - добавляет юзера в коллекцию (в свойство users) и устанавливает связь между "друзьями",
removeUser() - удаляет юзера из коллекции,
getUsers() - возвращает список всех "друзей". - По данным аннотациям Doctrine создаст вспомогательную таблицу friends, в которой будет 2 поля: id одного и второго "друга".
Так как у нас пример Self-referencing связи, оба связывающих поля и все 6 методов, управляющих ими находятся в одной сущности.
<?php namespace AppBundle\Entity; use Doctrine\ORM\Mapping as ORM; use Doctrine\Common\Collections\ArrayCollection; /** * @ORM\Entity * @ORM\Table(name="`user`") */ class User { /** * @var int * * @ORM\Id * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="SEQUENCE") * @ORM\SequenceGenerator(sequenceName="user_id_seq", allocationSize=1, initialValue=1) */ protected $id; /** * Many Users have Many Users. * * @var ArrayCollection * * @ORM\ManyToMany(targetEntity="User", mappedBy="myFriends") */ protected $friendsWithMe; /** * Many Users have many Users. * * @var ArrayCollection * * @ORM\ManyToMany(targetEntity="User", inversedBy="friendsWithMe") * @ORM\JoinTable(name="friends", * joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")}, * inverseJoinColumns={@ORM\JoinColumn(name="friend_user_id", referencedColumnName="id")} * ) */ protected $myFriends; public function __construct() { parent::__construct(); $this->friendsWithMe = new ArrayCollection(); $this->myFriends = new ArrayCollection(); } /** * @return ArrayCollection */ public function getFriendsWithMe() { return $this->friendsWithMe; } /** * @param User $myFriend * * @return User */ public function addMyFriend(User $myFriend) { if (!$this->myFriends->contains($myFriend)) { $this->myFriends[] = $myFriend; $myFriend->friendsWithMe[] = $this; } return $this; } /** * @param User $myFriend */ public function removeMyFriend(User $myFriend) { $this->myFriends->removeElement($myFriend); $myFriend->friendsWithMe->removeElement($this); } /** * @return ArrayCollection */ public function getMyFriends() { return $this->myFriends; } }
Контроллер
- Метод addMyFriend() -- или метод, в аннотации которого Вы указали описание таблицы friends
$activeUser->addMyFriend($friend);
- запишет idшники "друзей" в БД
- можно будет достать друзей $activeUser-a так:
$activeUser->getMyFriends();
- можно будет найти activeUser-а среди "друзей" friend-а так:
$friend->getFriendsWithMe();
- Нельзя (будет пустым):
- достать тех, кто "дружит" с activeUser-ом
$activeUser->getFriendsWithMe();
- достать всех "друзей" friend-а
$friend->getMyFriends();
- достать тех, кто "дружит" с activeUser-ом
- Метод addFriendsWithMe() -- или метод, в аннотации которого Вы указали описание таблицы friends мы перенесли внутрь addMyFriend().
- не запишет данные в БД, но добавляет объект пользователя в поле $FriendsWithMe
- можно будет достать друзей пользователя friend, если для activeUser-a (и других друзей) был запущен метод addMyFriends() так:
$friend->getFriendsWithMe()
- Обратите внимание на то, что если удалить данные из таблицы friends, данные в полях $MyFriends и $FriendsWithMe сохранятся, и все методы будут работать
ИТАК
В нашем случае для создания связей в контроллере целесообразно использовать методы добавления друзей в обе стороны:
$activeUser->addMyFriend($friend); $friend->addMyFriend($activeUser);
Для удаления, соответственно, методы remove:
$activeUser->removeMyFriend($friend); $friend->removeMyFriend($activeUser);
Возможно чтобы не было лишних методов, необходимо настраивать unidirectional (однонаправленную) связь.
- Log in to post comments
- 5936 reads
vedro-compota
Thu, 11/09/2017 - 13:12
Permalink
Entity User и Контроллер
Entity User и Контроллер лучше сделать H2 -- как и любые подзаголовки такого уровня. А не жирным
_____________
матфак вгу и остальная классика =)