Symfony2 Doctrine2使用集合-表演

卢卡斯·卢卡奇(Lukas Lukac)

这个问题的重点是弄清楚哪种技术更好,并听取了一些熟练的symfony2编码人员的不同意见。

将以挑战和“挑战等级”表为例,许多人可以对某些挑战进行评级。(类似于stackoverflow投票问题系统)。

这些表如下所示:(like_dislike是布尔值(1 =喜欢,0 =不喜欢)

挑战表 挑战等级表

挑战的数据量为10-200 +。


使用收藏

挑战实体

/**
 * Challanges
 *
 * @ORM\Table(name="challanges")
 * @ORM\Entity(repositoryClass="TB\ChallangesBundle\Entity\ChallangesRepository")
 */
class Challanges
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255)
     * @Assert\NotBlank()
     */
    private $name;

    /**
     * @var string
     *
     * @ORM\Column(name="slug", type="string", length=255, unique=true)
     */
    private $slug;

    /**
     * @var string
     *
     * @ORM\Column(name="description", type="text")
     * @Assert\NotBlank()
     */
    private $description;

    /**
     * @var \DateTime
     * @ORM\Column(name="start_date", type="datetime", nullable=false)
     * @Assert\DateTime()
     */
    private $start_date;

    /**
     * @var \DateTime
     * @ORM\Column(name="end_date", type="datetime", nullable=false)
     * @Assert\DateTime()
     */
    private $end_date;

    /**
     * @ORM\ManyToOne(targetEntity="TB\UserBundle\Entity\User", fetch="EXTRA_LAZY")
     * @ORM\JoinColumn(name="owner_id", referencedColumnName="id", nullable=false)
     */
    protected $owner;

    /**
     * @ORM\OneToMany(targetEntity="TB\ChallangesBundle\Entity\ChallangeRating", mappedBy="challange", cascade={"persist", "remove"})
     */
    protected $likes;

/**
 * Constructor
 */
public function __construct()
{
    $this->likes = new \Doctrine\Common\Collections\ArrayCollection();
}


/**
 * Add likes
 *
 * @param \TB\ChallangesBundle\Entity\ChallangeRating $likes
 * @return Challanges
 */
public function addLike(\TB\ChallangesBundle\Entity\ChallangeRating $likes)
{
    $this->likes[] = $likes;

    return $this;
}

/**
 * Remove likes
 *
 * @param \TB\ChallangesBundle\Entity\ChallangeRating $likes
 */
public function removeLike(\TB\ChallangesBundle\Entity\ChallangeRating $likes)
{
    $this->likes->removeElement($likes);
}

/**
 * Get likes
 *
 * @return \Doctrine\Common\Collections\Collection 
 */
public function getLikes()
{
    return $this->likes;
}

public function filterLikesInChallenge($like_dislike) {
    $criteria = Criteria::create();
    $criteria->where(Criteria::expr()->eq('like_dislike', $like_dislike));

    return $this->likes->matching($criteria);
}

public function checkIfUserRatedAlready(\TB\UserBundle\Entity\User $user)
{
    $criteria = Criteria::create();
    $criteria->where(Criteria::expr()->eq('fan', $user));

    return $this->likes->matching($criteria);
}

挑战等级实体

<?php

namespace TB\ChallangesBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * ChallangeRating
 *
 * @ORM\Table(name="challange_rating")
 * @ORM\Entity(repositoryClass="TB\ChallangesBundle\Entity\ChallangeRatingRepository")
 */
class ChallangeRating
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var boolean
     *
     * @ORM\Column(name="like_dislike", type="boolean")
     */
    private $like_dislike;

    /**
     * @ORM\ManyToOne(targetEntity="TB\UserBundle\Entity\User", inversedBy="fans")
     */
    protected $fan;

    /**
     * @ORM\ManyToOne(targetEntity="TB\ChallangesBundle\Entity\Challanges", inversedBy="likes")
     */
    protected $challange;


    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Get like_dislike
     *
     * @return boolean 
     */
    public function getLikeDislike()
    {
        return $this->like_dislike;
    }

    /**
     * Set like_dislike
     *
     * @param boolean $like_dislike
     * @return ChallangeRating
     */
    public function setLikeDislike($like_dislike)
    {
        $this->like_dislike = $like_dislike;

        return $this;
    }

    /**
     * Set fan
     *
     * @param \TB\UserBundle\Entity\User $fan
     * @return ChallangeRating
     */
    public function setFan(\TB\UserBundle\Entity\User $fan = null)
    {
        $this->fan = $fan;

        return $this;
    }

    /**
     * Get fan
     *
     * @return \TB\UserBundle\Entity\User 
     */
    public function getFan()
    {
        return $this->fan;
    }

    /**
     * Set challange
     *
     * @param \TB\ChallangesBundle\Entity\Challanges $challange
     * @return ChallangeRating
     */
    public function setChallange(\TB\ChallangesBundle\Entity\Challanges $challange = null)
    {
        $this->challange = $challange;

        return $this;
    }

    /**
     * Get challange
     *
     * @return \TB\ChallangesBundle\Entity\Challanges 
     */
    public function getChallange()
    {
        return $this->challange;
    }
}

好的,现在我要:

  1. 显示挑战详细信息
  2. 显示率功能(喜欢,不喜欢)以及喜欢和不喜欢的次数
  3. 显示已对此挑战进行评分的所有用户的列表

控制器

从获得挑战开始就如此经典

// this will take care of point number 1 (display challenge details) (1.)
$challange = $challangesRepo->findOneBy(array('slug'=>$slug)); 

// display numbers of likes and dislikes for certain challenge (2.)

但是现在有一个决定...

问题1

我应该通过从querybuilder中查询数据库来获得赞吗?(经典选择计数)

或者

我应该使用这样的集合和条件吗?

    $challangeLikes = $challange->filterLikesInChallenge(1);
    $challangeDislikes = $challange->filterLikesInChallenge(0);

**什么是更好的内存使用率?什么对数据库性能更好?**

如果我没有记错的话,以下两个查询将通过这两个方法执行:

SELECT 
  t0.id AS id1, 
  t0.like_dislike AS like_dislike2, 
  t0.fan_id AS fan_id3, 
  t0.challange_id AS challange_id4 
FROM 
  challange_rating t0 
WHERE 
  (
    t0.like_dislike = ? AND t0.challange_id = ? 
  )
Parameters: [1, 12] 

SELECT 
  t0.id AS id1, 
  t0.like_dislike AS like_dislike2, 
  t0.fan_id AS fan_id3, 
  t0.challange_id AS challange_id4 
FROM 
  challange_rating t0 
WHERE 
  (
    t0.like_dislike = ? AND t0.challange_id = ? 
  )

现在,我可以将喜欢,不喜欢的次数传递给视图,如下所示:

'challangeLikes'=>$challangeLikes->count(),
'challangeDislikes'=>$challangeDislikes->count(),

问题2

如果我想知道某些用户是否已经对此挑战进行评分,该怎么办?

再次...

*我应该使用带有选择计数的经典querybuilder样式吗*

或者

我应该使用类似的方法:

$ratedAlreadyCol = $challange->checkIfUserRatedAlready($user)->first();

那实际上会执行另一个查询吗?像经典的选择计数之类的东西,但是集合会帮我做这个吗?因此,这不是在所有具有大喜乐的大型内存阵列中进行搜索,而是对DB的查询?

SELECT 
  t0.id AS id1, 
  t0.like_dislike AS like_dislike2, 
  t0.fan_id AS fan_id3, 
  t0.challange_id AS challange_id4 
FROM 
  challange_rating t0 
WHERE 
  (
    t0.fan_id = ? AND t0.challange_id = ? 
  )
Parameters: [25, 12] 

问题3-可能对表演最重要

我想展示所有“粉丝-评出特定挑战的人” ...

再次...

我是否应该在存储库中创建单独的querybuilder方法,并通过内部连接到用户表来选择某些挑战的所有评级(因此我可以显示个人资料图片和用户名)

或者

我是否应该获得所有收视率,并在树枝循环中像这样:

 $challangeLikesCollection = $challange->getLikes();

{% for bla bla

如果我这样做的话...教义将为循环中的每个“粉丝”对用户表执行一个选择查询...并且何时会有这样的说法... 200粉丝...那不是很好吗?

奖金问题

能以某种方式请他提供处理这些情况的方法吗?有什么建议?

还是您使用其他任何技术?

我非常关心内存使用率和数据库加载时间,因为它将在任何地方使用,并且每个用户都会遇到这样的列表,并面临不同的挑战。清单将包括15个挑战,并将所有喜欢,不喜欢的事物与列表中的每个挑战联系起来,等等。

感谢您的解释,提示和提示,它们将帮助我和其他读者迈上另一个台阶!

1ed

我将执行以下操作:

  1. 非规范化一点,添加number of likesnumber of dislikes领域Challenge,并更新这些值addLikeremoveLike

  2. 重命名like_dislike为,like因为它是一个布尔字段,并且1表示喜欢0表示不喜欢

  3. 使用单独的查询来查询用户列表,并使用数组水化和INDEXBY用户名(它必须是唯一的或用户ID),或者可以创建自定义水化器

    选择u.username,u.photo从用户u INNER JOIN用r.fan = u进行评估u.username

    或类似的东西。并且您可以检查当前用户的用户名是否在数组中。

我认为这可能足够出色。

一些解释:

INDEX BY表示结果集合或数组键(索引)将是一个字段的值(此字段必须是唯一的)。当您使用INDEX BY时,结果集将包含已知键,因此您可以在恒定时间内直接获取(例如检查是否存在)单个结果(不必搜索整个结果集)。

Doctrine在下面使用PDO,水合作用意味着如何处理PDO结果集并将其转换为其他内容。默认的对象水合意味着将结果集转换为对象图,这是非常昂贵的操作。还有其他一些较便宜的水合作用模式,但是您失去了易用性。例如,如果您使用数组水合作用,那么结果将是一个数组数组,因此您无法对其进行修改(我的意思是将其持久化回到数据库中),因此它仅用于读取,结果不是实体对象,因此您无法使用其方法,例如自定义吸气剂。您可以根据需要创建自定义水龙头

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章