5

I have set up a bundle that has a test object which holds a number of testQuestion objects each of which is a question and the given answer (or 0 if no answer). From twig I want to be able to get the information from the test object to say how many questions there are and how many have been answered.

I have created a query to pull this out of the db, and in the Test Entity I have created 2 new properties to store the number of questions and the number answered. I have created a TestRepository inside which the query resides. The Test object checks to see if the object has the value set and if not loads it when needed as I won't always need this information.

However I'm stuck on how to link the repository code to the test object, both to call the repo function and for the repo function to save the values to the relevant Test object.

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 (There's a matching method for 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);
    }

1 Answer 1

12

There are a number of different patterns you can use to achieve this result, the simplest of which is to simply use an aggregate field. This stores the information after it's modified, rather than calculating it each time that it's needed.

An alternate solution is to create a one-to-many association between your Test and TestQuestion repositories (assuming that there isn't one already), then in your twig template you can simply use {{ testEntity.questionsAnswered.count() }} - you can even tell Doctrine to make this an "extra-lazy" association so that it uses the COUNT SQL statement to look up how many answered questions there are (by default it actually fetches the question entities when you try to enumerate the association).

Finally, there's the method that I wouldn't recommend highly, but might be required depending on your situation. Similar to the approach that you use in your question, you fetch the question count in your repository, but to keep with Symfony's simple Model approach, you don't kick off the query from inside the entity (as the entity should never have information about the entity manager/repository).

Instead, you can use a Doctrine EventListener to be informed whenever an instance of your Test entity is loaded (see here, using the postLoad event), then call your repository method and set it on the entity from there.

Sign up to request clarification or add additional context in comments.

1 Comment

Beware!!1 With extra-lazy associations you must use Collection#count() call instead of built-in twig lenght. Correct way that will use SQL COUNT: {{ testEntity.questionsAnswered.count }} (|length will cause fetching rows in memory!)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.