Symfony2/Doctrine:如何仅为当前登录用户加载相关对象



我的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仍然是一个数组,但是如果您对评级有限制,因此用户只能对歌曲进行一次评级,那么第一个评级将是该用户评级。

相关内容

  • 没有找到相关文章

最新更新