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
- 6974 reads
vedro-compota
Thu, 11/09/2017 - 13:12
Permalink
Entity User и Контроллер
Entity User и Контроллер лучше сделать H2 -- как и любые подзаголовки такого уровня. А не жирным
_____________
матфак вгу и остальная классика =)