5

我已经设置了一个包含一个测试对象的包,该测试对象包含许多 testQuestion 对象,每个对象都是一个问题和给定的答案(如果没有答案,则为 0)。从 twig 我希望能够从测试对象中获取信息,以说明有多少问题以及已经回答了多少问题。

我创建了一个查询以将其从数据库中提取出来,并在测试实体中创建了 2 个新属性来存储问题的数量和回答的数量。我创建了一个 TestRepository ,查询所在的位置。Test 对象检查对象是否设置了值,如果没有,则在需要时加载它,因为我并不总是需要这些信息。

但是,我坚持如何将存储库代码链接到测试对象,既要调用 repo 函数,又要让 repo 函数将值保存到相关的 Test 对象。

Acme/Quizbundle/Test/Test.php

namespace Acme\QuizBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Acme\QuizBundle\Entity\TestRepository;

/**
 * @ORM\Entity(repositoryClass="Acme\QuizBundle\Entity\TestRepository")
 * @ORM\Table(name="test")
 */
class Test    {
protected $numQuestions = null;
protected $numQuestionsAnswered = null;

public function getNumQuestionsAnswered () {
    if (is_null($this->numQuestionsAnswered)) {
        $repository = $this->getEntityManager()->getRepository('\AcmeQuizBundle\Test');
        $values = $repository->calculateNumQuestions();
    }
    return $this->numQuestionsAnswered;
}

Acme/Quizbundle/Test/TestRepository.php (getNumQuestions() 有匹配方法)

namespace Acme\QuizBundle\Entity;

use Doctrine\ORM\EntityRepository;

class TestRepository extends EntityRepository {

private function calculateNumQuestions() {

    $qb = $this->getEntityManager()
                ->createQueryBuilder();

    $query = $this->getEntityManager()->createQueryBuilder()
                        ->select('COUNT(id)')
          ->from('testquestion', 'tq')
          ->where('tq.test_id = :id')
          ->setParameter('id', $this->getId())
          ->getQuery();

    $result = $query->getSingleScalarResult();
    var_dump($result);
    }
4

1 回答 1

12

您可以使用许多不同的模式来实现此结果,其中最简单的是简单地使用聚合字段。这会在修改后存储信息,而不是每次需要时都计算它。

另一种解决方案是在您的 Test 和 TestQuestion 存储库之间创建一对多关联(假设还没有),然后在您的 twig 模板中您可以简单地使用{{ testEntity.questionsAnswered.count() }}- 您甚至可以告诉 Doctrine 将其设为“ extra-lazy”关联,以便它使用 COUNT SQL 语句来查找有多少已回答的问题(默认情况下,当您尝试枚举关联时,它实际上会获取问题实体)。

最后,我不强烈推荐这种方法,但根据您的情况可能需要。与您在问题中使用的方法类似,您在存储库中获取问题计数,但为了与 Symfony 的简单模型方法保持一致,您不会从实体内部启动查询(因为实体不应该有关于实体管理器/存储库)。

相反,您可以使用 Doctrine EventListener 在加载您的 Test 实体的实例时被通知(参见此处,使用 postLoad 事件),然后调用您的存储库方法并从那里将其设置在实体上。

于 2012-07-14T10:27:23.410 回答