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);
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With