В моем коде Symfony я использовал Doctrine. В Entity (AppBundle \ Entity \ Core \ User) я определил столбец foodTypes, который связан с другим Entity (AppBundle \ Entity \ FoodRecording \ FoodType). Я определил отношение «многие ко многим» между пользователем и FoodType с помощью таблицы ссылок foodrecording_user, присоединяющейся к User.username и FoodType.foodtype_code. Код показан ниже.
// Entity\Core\User
namespace AppBundle\Entity\Core;
......
class User implements AdvancedUserInterface, \Serializable {
......
/**
* @ORM\ManyToMany(targetEntity = "AppBundle\Entity\FoodRecording\FoodType")
* @ORM\JoinTable(name = "foodrecording_user",
* joinColumns = {@ORM\JoinColumn(name = "username", referencedColumnName = "username", onDelete = "CASCADE")},
* inverseJoinColumns = {@ORM\JoinColumn(name = "foodtype_code", referencedColumnName = "code", onDelete = "CASCADE")}
* )
*/
private $foodTypes;
public function getFoodTypes()
{
$this->foodTypes = new \Doctrine\Common\Collections\ArrayCollection();
return $this->foodTypes;
}
Однако, поскольку я хотел напрямую получить все типы еды определенного пользователя, используя
$userFoodTypes = $this->get('security.token_storage')->getToken()->getUser()->getFoodTypes();
тогда я получил
$userFoodTypes =====> array[]
Я ожидал, что, когда я создал отношение M-M, Doctrine автоматически извлечет нужные мне данные, но это не так!
Поэтому мне нужно написать свой собственный код для извлечения данных из БД / таблицы, как показано ниже:
public function fetchUserFoodTypes()
{
global $kernel;
$container = $kernel->getContainer();
$em = $container->get('doctrine.orm.entity_manager');
$conn = $em->getConnection();
$sql = 'SELECT * FROM foodrecording_user where username = :username';
$stmt = $conn->prepare($sql);
$stmt->execute([
'username' => $this->getUsername(),
]);
$data = $stmt->fetchAll();
$res = [];
foreach ($data as $item) {
$foodtype = $em->getRepository('AppBundle\Entity\FoodRecording\FoodType')->findByCode($item['foodtype_code']);
$res[] = $foodtype;
}
return $res;
}
public function getFoodTypes()
{
$this->foodTypes = $this->fetchUserFoodTypes();
//$this->foodTypes = new \Doctrine\Common\Collections\ArrayCollection();
return $this->foodTypes;
}
Только так я могу получить типы еды, связанные с пользователем.
Может ли кто-нибудь объяснить мне, почему я не могу просто использовать определение M-M и позволить доктрине делать все автоматически за меня? Почему я должен явно писать собственную функцию для извлечения данных из БД? Разве Доктрина недостаточно умна?




Эта часть:
$this->foodTypes = new \Doctrine\Common\Collections\ArrayCollection();
Принадлежит к методу __construct, а не к геттеру. Как видите, каждый раз, когда вы вызываете геттер, вы сбрасываете свойство foodTypes на пустой экземпляр ArrayCollection.