My Symfony2 application displays songs and lets the user rate them. User Management is done with FOSUserBundle. I have defined an One-To-Many Relationship between two Objects (Song & Ratings) defined like this:
Entity/Song.php
/**
* Song
*
* @ORM\Table()
* @ORM\Entity(repositoryClass="[...]\[...]Bundle\Entity\SongRepository")
*/
class Song
{
[...]
/**
* @ORM\OneToMany(targetEntity="Rating", mappedBy="song")
*/
protected $ratings;
[...]
}
and
Entity/Rating.php
/**
* Rating
*
* @ORM\Table()
* @ORM\Entity
*/
class Rating
{
[...]
/**
* @var float
*
* @ORM\Column(name="rating", type="float")
*/
private $rating;
/**
* @ORM\ManyToOne(targetEntity="[...]\UserBundle\Entity\User", inversedBy="ratings")
* @ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
protected $user;
/**
* @ORM\ManyToOne(targetEntity="Song", inversedBy="ratings")
* @ORM\JoinColumn(name="song_id", referencedColumnName="id", onDelete="CASCADE")
*/
protected $song;
[...]
When loading all the songs (~40) in my application I can access them in the controller like this:
SongsController.php:
$songs = $em->getRepository('[...]Bundle:Song')->findAll();
Now, how can I efficiently make sure that I only get the rating of the currently logged in user, without iterating through all ratings and validating the user?
index.html.twig:
{% for rating in song.ratings %}
{% if rating.user == app.user%}
{{ rating.rating }}
{% endif %}
{% endfor %}
EDIT:
I have this now:
public function getAllSongsWithRatings($user)
{
$qb = $this->getEntityManager()->createQueryBuilder()
->select('s')
->from('[...]Bundle:Song','s')
->join('s.ratings','r')
->where('r.user = :user')
->setParameter('user', $user);
return $qb->getQuery()->getResult();
}
But when I look what doctrine generates:
SELECT s0_.id AS id0, s0_.number [...] FROM Song s0_ LEFT JOIN Rating [...] WHERE r1_.user_id = ? AND [...]
SELECT t0.id AS id1, t0.rating AS [...] FROM Rating t0 WHERE t0.song_id = ?
It does not query for the rating, including the user_id... I think this is possibly imperformant...