2012-07-13 101 views
5

我建立了一个包含一个测试对象的包,其中包含多个testQuestion对象,每个对象都是问题和给定的答案(如果没有答案,则为0 )。从树枝上我希望能够从测试对象中获取信息,说明存在多少个问题以及有多少个答案。Symfony2/Doctrine如何在实体中存储相关对象的数量

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

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

的Acme/Quizbundle /测试/ 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 /测试/ 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); 
    } 

回答

12

有许多你可以使用不同的图案来达到这个效果,其中最简单的就是简单地使用aggregate field。这会在修改后存储信息,而不是在每次需要时计算它。

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

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

相反,只要加载了Test实体的实例(请参阅here,使用postLoad事件),就可以使用Doctrine EventListener来通知您,然后调用您的存储库方法并将其设置在实体上。

+0

谢谢,这真的很有帮助 – 2012-07-14 15:19:53

+0

要小心!! 1如果使用额外的懒惰关联,您必须使用'Collection#count()'call **来代替内置的小枝**'lenght'。 **正确的方法将使用SQL COUNT:**'{{testEntity.questionsAnswered.count}}'('| length'将导致在内存中获取行!) – 2017-01-29 09:53:20

+0

感谢您更正@Sanya_Zol,相应地更新了答案 – 2017-01-29 13:57:09

相关问题