问题
I have a page that displays information about a movie. I recover in GET the id of the film. What I would like to do is retrieve the comments for each film (there is a filmId column in my table linked to the primary id of the film table)
/**
* @Route("/user/film/{id}", name="film")
*/
public function film(FilmRepository $repo, CommentRepository $comRepo, EntityManagerInterface $em, Request $req, $id)
{
$film = $repo->find($id);
$comments = $comRepo->findBy(array('id' => $id));
return $this->render('film/film.html.twig', [
'controller_name' => 'FilmController',
'film' => $film,
'comments' => $comments
]);
}
when I make a $comments = $comRepo->findBy(array('id' => $id)); I get some comments, but based on their id and NOT the film id (the comment with id 1 will be displayed on the film with id 1, but for example a comment with id 4 and the filmId a 1 will not appear on film 1, but on the film with id 4)
I tried to access the filmId field by simply making a $comments = $comRepo->findBy(array ('filmId' => $ id)); but i get the error :
An exception occurred while executing 'SELECT t0.id AS id_1, t0.content AS content_2, t0.created_at AS created_at_3, t0.author_id AS author_id_4 FROM comment t0 WHERE comment_film.film_id = ?' with params ["1"]: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'comment_film.film_id' in 'where clause'
I tried a personalized request with, in my Comment repository:
public function findAllWithFilmId($filmId)
{
$em = $this->getEntityManager();
$query = $em->createQuery(
'SELECT c
FROM App\Entity\Comment c
WHERE c.filmId = :filmId'
)->setParameter('filmId', $filmId);
return $query->getResult();
}
But it doesn't seem to work..
Where do I go to make a request like this ? How to modify the request, which seems erroneous, from symfony without disorganizing everything? or is there a better method to correct the problem?
This is my Comment Entity
<?php
namespace App\Entity;
use App\Entity\Film;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="App\Repository\CommentRepository")
*/
class Comment
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="comments")
* @ORM\JoinColumn(nullable=false)
*/
private $author;
/**
* @ORM\ManyToMany(targetEntity="App\Entity\Film", inversedBy="comments")
* @ORM\JoinColumn(nullable=false)
*/
private $filmId;
/**
* @ORM\Column(type="text")
*/
private $content;
/**
* @ORM\Column(type="datetime")
*/
private $createdAt;
public function getId(): ?int
{
return $this->id;
}
public function getAuthor(): ?User
{
return $this->author;
}
public function setAuthor(?User $author): self
{
$this->author = $author;
return $this;
}
public function getFilmId(): ?Film
{
return $this->filmId;
}
public function setFilmId(?Film $filmId): self
{
$this->filmId = $filmId;
return $this;
}
public function getContent(): ?string
{
return $this->content;
}
public function setContent(string $content): self
{
$this->content = $content;
return $this;
}
public function getCreatedAt(): ?\DateTimeInterface
{
return $this->createdAt;
}
public function setCreatedAt(\DateTimeInterface $createdAt): self
{
$this->createdAt = $createdAt;
return $this;
}
}
I think it is possible that the error comes from annotations, because starting on symfony during the make: entity, I defined types relations which I corrected later in phpmyadmin, but not the code. For example we can see that filmId is in ManyToMany, but I think it should be in OneToOne (FilmId can only have one id and an id can only correspond to one filmId), but I'm afraid that if I change certain things it breaks everything.
回答1:
If you have set up your ORM relations correctly, it should be as simple as:
$film = $repo->find($id);
$comments = $film->getComments();
You might be missing a mapping in Film.php.
Here's an XML example, should be easy enough to convert to annotations:
In film:
<one-to-many field="comments" target-entity="App\...\Comments" mapped-by="film"/>
In comments:
<many-to-one field="film" target-entity="App\...\Film" inversed-by="comments"/>
回答2:
First of all, I advise you to read more about the relations between entities.
Because, the current annotations says that you can have a lot of comments on many films. It's not right. One comment may belong to one film. One movie can have many comments.
Also, I want to note that, as far as I know, @JoinColumn should be in a child entity, that is, where the link to FK is contained. Therefore, your entities should look like this:
Comment:
<?php
namespace App\Entity;
use App\Entity\Film;
use DateTimeInterface;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="App\Repository\CommentRepository")
*/
class Comment
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="comments")
*/
private $author;
/**
* @ORM\ManyToOne(targetEntity="App\Entity\Film", inversedBy="comments")
* Here we set property for our table and property of foreign table to map our comment to the right film
* nullable, because comment couldn't be without film
* @ORM\JoinColumn(name="film_id", referencedColumnName="id", nullable=false)
*/
private $film;
/**
* @ORM\Column(type="text")
*/
private $content;
/**
* @ORM\Column(type="datetime")
*/
private $createdAt;
public function getId(): ?int
{
return $this->id;
}
public function getAuthor(): ?User
{
return $this->author;
}
public function setAuthor(?User $author): self
{
$this->author = $author;
return $this;
}
public function getFilmId(): ?Film
{
return $this->filmId;
}
public function setFilmId(?Film $filmId): self
{
$this->filmId = $filmId;
return $this;
}
public function getContent(): ?string
{
return $this->content;
}
public function setContent(string $content): self
{
$this->content = $content;
return $this;
}
public function getCreatedAt(): ?DateTimeInterface
{
return $this->createdAt;
}
public function setCreatedAt(DateTimeInterface $createdAt): self
{
$this->createdAt = $createdAt;
return $this;
}
}
Film:
<?php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="App\Repository\FilmRepository")
*/
class Film
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\OneToMany(targetEntity="App\Entity\Comment", mappedBy="film")
*/
private $comments;
public function __construct()
{
$this->comments = new ArrayCollection();
}
public function getId()
{
return $this->id;
}
public function setId($id)
{
$this->id = $id;
return $this;
}
public function getComments(): Collection
{
return $this->comments;
}
public function setComments(Collection $comments): Film
{
$this->comments = $comments;
return $this;
}
}
So, now, you can retrieve your comments via:
/**
* @Route("/user/film/{id}", name="film")
*/
public function film($id)
{
/** @var null|EntityManager $entityManager */
$entityManager = $this->get('doctrine.orm.entity_manager');
if (null == ($film = $entityManager->getRepository(Film::class)->find($id))){
throw new NotFoundHttpException('Film not found');
}
$comments = $film->getComments();
return $this->render('film/film.html.twig', [
'film' => $film,
'comments' => $comments
]);
}
来源:https://stackoverflow.com/questions/60851608/request-a-linked-field-in-symfony