У меня есть приложение Symfony с сущностью Comment , и я хотел бы связать его со свойством отношения со многими сущностями. Но под многими сущностями я имею в виду не много объектов, а множество классов .
A комментарий может быть о разных вещах в моем приложении: Рисунок сущность, Текст сущность, Compo сущность, или Фотография сущность. Каждый объект соответствует типу художественного произведения, у каждого из которых разные свойства и разные страницы. И каждый может быть оценен и прокомментирован .
Проблема в том, что когда я хочу создать свойство отношения в моей сущности Comment, я должен указать только ОДНУ сущность . Я хочу, чтобы некоторые комментарии касались рисованной сущности, некоторые - о тексте и т. Д.
Я вижу решение: создать один комментарий к сущности по сущности для ссылки, но в моем приложении будет очень много сущностей, и мой код будет дублирован, что не очень хорошо для будущих изменений и т. Д.
Есть ли способ связать одну сущность с множеством разных типов сущностей?
Спасибо.
РЕДАКТИРОВАТЬ 4: ВСЕ ПРЕДЫДУЩИЕ РЕДАКТИРОВКИ НИЖЕ БЕЗ БЕЗ БЕЗЖИСТЫХ!
Я позволил это, чтобы новички могли видеть часть моего кода, чтобы иметь подробный пример отображения наследования (я, который я мог иметь это, когда я пытался сначала, я не все понял), но я только что понял глупую ошибку, которую я сделал :
* @DiscriminatorMap({"comment" = "Comment", "comment" = "CommentDrawing", "commentphoto" = "CommentPhoto", "commenttexte" = "CommentTexte"})
- Я забыл "commentcompo" = "CommentCompo"
- Я написал "comment" = "Comment" И "comment" = "CommentDrawing" (на оба ссылается "comment")
Именно поэтому мне пришлось поставить «комментарий» в качестве дискриминатора вместо «комментирования».
Извините за эту глупую ошибку, Столько строк кода я не заметил.
А для тех, кто впервые использует отображение наследования и хочет получить информацию, я сейчас пытаюсь заполнить комментарии формами . Если вы хотите сделать то же самое (вы, вероятно, захотите, если вы пришли сюда за ответом), я думаю, что это решение :
https://symfony.com/doc/current/form/inherit_data_option.html
РЕДАКТИРОВАТЬ :
Благодаря ответу Джакуми ниже я использовал отображение наследования . Я выбрал первое решение: решение за одним столом . Но я попробовал, у меня нет сообщения об ошибке , но это не сработало для меня , и после нескольких часов я все еще не понимаю, что я сделал неправильно.
Мой Класс комментариев ( самый верхний класс моей иерархии комментариев , который имеет CommentDrawing, CommentCompo, CommentPhoto, CommentTexte в качестве детей) (комментарий является абстрактным, потому что У меня была ошибка, сообщавшая мне, что я должен описать ее абстрактно, чтобы устранить ошибку):
<?php
namespace App\Entity;
use App\Entity\Comment;
use App\Entity\CommentPhoto;
use App\Entity\CommentTexte;
use App\Entity\CommentDrawing;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Mapping\InheritanceType;
use Doctrine\ORM\Mapping\DiscriminatorMap;
use Doctrine\ORM\Mapping\DiscriminatorColumn;
/**
* @ORM\Entity(repositoryClass="App\Repository\CommentRepository")
* @InheritanceType("SINGLE_TABLE")
* @DiscriminatorColumn(name="discriminator", type="string")
* @DiscriminatorMap({"comment" = "Comment", "comment" = "CommentDrawing", "commentphoto" = "CommentPhoto", "commenttexte" = "CommentTexte"})
*/
abstract class Comment
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="datetime")
*/
private $createdAt;
/**
* @ORM\Column(type="text")
*/
private $content;
/**
* @ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="comments")
* @ORM\JoinColumn(nullable=false)
*/
private $author;
public function getId(): ?int
{
return $this->id;
}
public function getCreatedAt(): ?\DateTimeInterface
{
return $this->createdAt;
}
public function setCreatedAt(\DateTimeInterface $createdAt): self
{
$this->createdAt = $createdAt;
return $this;
}
public function getContent(): ?string
{
return $this->content;
}
public function setContent(string $content): self
{
$this->content = $content;
return $this;
}
public function getAuthor(): ?User
{
return $this->author;
}
public function setAuthor(?User $author): self
{
$this->author = $author;
return $this;
}
}
А вот и моя сущность CommentDrawing (я создал другие классы CommentSomething, но сейчас я пытался использовать только CommentDrawing):
<?php
namespace App\Entity;
use App\Entity\Comment;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="App\Repository\CommentDrawingRepository")
*/
class CommentDrawing extends Comment
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity="App\Entity\Dessin", inversedBy="commentsDrawing")
*/
private $drawing;
public function getId(): ?int
{
return $this->id;
}
public function getDrawing(): ?Dessin
{
return $this->drawing;
}
public function setDrawing(?Dessin $drawing): self
{
$this->drawing = $drawing;
return $this;
}
}
А вот сущность Дессин это относится к (Дессин рисует по-французски, я забыл назвать его английским именем, когда создавал его), это не дочерний класс класса Comment, это тема объекта CommentDrawing (связанный с ManyToOne), который сам является дочерним классом Comment:
<?php
namespace App\Entity;
use Cocur\Slugify\Slugify;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
/**
* @ORM\Entity(repositoryClass="App\Repository\DessinRepository")
* @ORM\HasLifecycleCallbacks
* @UniqueEntity(
* fields = {"nom"},
* message = "Un autre dessin contient le même nom. Merci de le changer. Vérifiez aussi que vous avez entré un slug unique, ou vide. Si le slug est en double, ça engendrera un bug.")
* @UniqueEntity(
* fields = {"url"},
* message = "Un autre dessin contient la même url, vous vous apprêtez à poster deux fois le même dessin. Merci de changer l'url.")
* )
*/
class Dessin
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
// Some code I hidden because it's useless to show
/**
* @ORM\Column(type="string", length=255)
*/
private $slug;
// Some code I hidden because it's useless to show
/**
* @ORM\OneToMany(targetEntity="App\Entity\CommentDrawing", mappedBy="drawing")
*/
private $commentsDrawing;
public function __construct()
{
// Some code I hidden
$this->commentsDrawing = new ArrayCollection();
}
// Some code I hidden
public function getId(): ?int
{
return $this->id;
}
// Some code I hidden
public function getSlug(): ?string
{
return $this->slug;
}
public function setSlug(string $slug): self
{
$this->slug = $slug;
return $this;
}
// Some code I hidden
/**
* @return Collection|CommentDrawing[]
*/
public function getCommentsDrawing(): Collection
{
return $this->commentsDrawing;
}
public function addCommentsDrawing(CommentDrawing $commentsDrawing): self
{
if (!$this->commentsDrawing->contains($commentsDrawing)) {
$this->commentsDrawing[] = $commentsDrawing;
$commentsDrawing->setDrawing($this);
}
return $this;
}
public function removeCommentsDrawing(CommentDrawing $commentsDrawing): self
{
if ($this->commentsDrawing->contains($commentsDrawing)) {
$this->commentsDrawing->removeElement($commentsDrawing);
// set the owning side to null (unless already changed)
if ($commentsDrawing->getDrawing() === $this) {
$commentsDrawing->setDrawing(null);
}
}
return $this;
}
}
Чтобы проверить, работает ли это правильно, я вручную создал комментарий в базе данных с помощью phpmyadmin:
Затем я попытался показать содержание комментария к рисунку выше на странице, используя переменную рисунка, соответствующую чертежу, являющемуся предметом моего комментария. Ничего не случилось. Так что Я непосредственно пытался сбросить его в контроллер, невозможно получить комментарий .
Чтобы получить комментарий, я использовал свойство $ commentsDrawing объекта Drawing (вы можете увидеть его в приведенном выше коде). Вот код, который я использовал для создания дампа var чертежа, который должен содержать комментарий (я поместил функцию dump () в функцию show, то есть вызов с параметром draw в качестве параметра, созданного в URL. Я уверен, что show () Функция работает правильно и показывает хороший рисунок, потому что я проверял это раньше). Это DrawingController :
<?php
namespace App\Controller;
use App\Entity\Dessin;
use App\Form\DrawingType;
use App\Entity\CategorieDessin;
use App\Service\PaginationService;
use App\Repository\DessinRepository;
use App\Repository\CategorieDessinRepository;
use Symfony\Component\HttpFoundation\Request;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class DrawingsController extends AbstractController
{
// I hide the rest of the code because it's useless
/**
* show a drawing
*
* @Route("/dessin/{slug}", name="drawing_show")
*
* @return Response
*/
public function show(Dessin $drawing)
{
dump($drawing);
die();
return $this->render('drawings/show.html.twig', [
'drawing' => $drawing
]);
}
}
Что показывает дамп ():
Как видите, в комментариях> коллекция, без элементов .
Если я сделаю то же самое без функции dump (), я получу чертеж, без ошибок, но и без комментариев.
Я действительно не понимаю, что я сделал не так ... Может кто-нибудь, пожалуйста, помогите?
РЕДАКТИРОВАТЬ 2 :
Когда я делаю это:
/**
* show a drawing
*
* @Route("/dessin/{slug}", name="drawing_show")
*
* @return Response
*/
public function show(Dessin $drawing, CommentDrawingRepository $repo)
{
$comments = $repo->findAll();
dump($comments);
die();
return $this->render('drawings/show.html.twig', [
'drawing' => $drawing
]);
}
Я получаю пустой массив
РЕДАКТИРОВАТЬ 3 :
Ну, я добавил новый CommentDrawing прямо из моего DrawingController:
/**
* show a drawing
*
* @Route("/dessin/{slug}", name="drawing_show")
*
* @return Response
*/
public function show(Dessin $drawing, CommentDrawingRepository $repo, DessinRepository $repoDrawing, UserRepository $repoUser, ObjectManager $manager)
{
$drawing = $repoDrawing->findAll()[0];
$user = $repoUser->findAll()[0];
$comment = new CommentDrawing();
$comment->setCreatedAt(new \DateTime())
->setContent("un test")
->setAuthor($user)
->setDrawing($drawing);
$manager->persist($comment);
$manager->flush();
$comments = $repo->findAll();
dump($comments);
return $this->render('drawings/show.html.twig', [
'drawing' => $drawing
]);
}
И , который работал . Комментарий регистрируется в базе данных, дамп показывает комментарий, и комментарий появляется на моей странице.
Я пытался понять, почему комментарий, добавленный с помощью phpmyadmin, не работал, и что удивительно: разница между обоими комментариями заключается в том, что комментарий, добавленный с помощью phpmyadmin, имеет commentdrawing как значение дикриминатора и добавленный доктриной только что комментирует как значение ... Что является значением для абстрактного класса ! Я думал, что значение дискриминатора было бы полезно, чтобы сообщить доктрине, какой столбец нужно рассмотреть, я больше не понимаю ... Но хорошо, проблема решена . Спасибо за вашу помощь!
примечание: второй - тот, который работал ... Почему?