我的Symfony2应用程序显示歌曲并让用户对它们进行评分。用户管理是通过FOSUserBundle完成的。我定义了两个对象(歌曲和评级)之间的一对多关系,定义如下:
实体/歌曲.php
/**
* Song
*
* @ORMTable()
* @ORMEntity(repositoryClass="[...][...]BundleEntitySongRepository")
*/
class Song
{
[...]
/**
* @ORMOneToMany(targetEntity="Rating", mappedBy="song")
*/
protected $ratings;
[...]
}
和
实体/评级.php
/**
* Rating
*
* @ORMTable()
* @ORMEntity
*/
class Rating
{
[...]
/**
* @var float
*
* @ORMColumn(name="rating", type="float")
*/
private $rating;
/**
* @ORMManyToOne(targetEntity="[...]UserBundleEntityUser", inversedBy="ratings")
* @ORMJoinColumn(name="user_id", referencedColumnName="id")
*/
protected $user;
/**
* @ORMManyToOne(targetEntity="Song", inversedBy="ratings")
* @ORMJoinColumn(name="song_id", referencedColumnName="id", onDelete="CASCADE")
*/
protected $song;
[...]
在我的应用程序中加载所有歌曲 (~40) 时,我可以像这样在控制器中访问它们:
歌曲控制器.php:
$songs = $em->getRepository('[...]Bundle:Song')->findAll();
现在,如何有效地确保我只获取当前登录用户的评级,而无需循环访问所有评级并验证用户?
索引.html.twig:
{% for rating in song.ratings %}
{% if rating.user == app.user%}
{{ rating.rating }}
{% endif %}
{% endfor %}
编辑:
我现在有这个:
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();
}
但是当我看教义产生什么时:
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 = ?
它不会查询评级,包括user_id...我认为这可能是不合格的...
您需要使用存储库函数:
http://symfony.com/doc/current/book/doctrine.html#custom-repository-classes
然后我们必须获得一些原始来运行本机MySQL查询:
public function getSongsWithUserRatings($userid)
{
$stmt = $this->_em->getConnection()->executeQuery(
'SELECT * FROM Song s LEFT JOIN Rating r ON r.song = s.song_id AND r.user = :userid',
array('userid'=>$userid),
array('userid'=>'integer')
);
return $stmt->fetchAll();
请注意左侧连接部分。 使用 WITH 参数将为您提供所有歌曲以及加入该评级(如果它们仅来自该用户)。
然后在你的控制器中,你调用这个并将其传递给树枝:
//Controller
$userRatedSongs = $em->getRepository('Bundle:Songs')->getSongsWithUserRatings($this->getUser()->getUserId())
然后你的树枝模板:
{% for song in songs %}
<h3>{{song.name}}</h3>
{% if song.rating != null %}
<p> Rating: {{song.rating}}</p>
{% endif %}
{% endfor %}
song.ratings仍然是一个数组,但是如果您对评级有限制,因此用户只能对歌曲进行一次评级,那么第一个评级将是该用户评级。