Search code examples
symfonydoctrine-ormassociationsdoctrine-extensions

symfony3 doctrine2 association counter field


Consider the following case: I have two entities: Article and ArticleComment:

// \AppBundle\Entity\Article

/**
 * @ORM\OneToMany(targetEntity="ArticleComment", mappedBy="article")
 */
private $comments;

I need to store the amount of comments in a field on the article (eg. articles.comments_count). The field needs to be updated whenever a comment is created or deleted.

Previously I used the CakePHP framework which has built-in CounterCache behavior which does this automatically. I've tried my best to find something similar for Doctrine 2 (starting with DoctrineExtensions library) but nothing seems to do what I'm looking for.

Any library that does this? Or do I have to come up with my own solution?

Edit: I've tried using Entity Events but I require this behavior on many entities so I'm interested in a reusable solution


Solution

  • Here is another answer which avoids storing this kind of aggregate and enables you to use the paginator as you've requested in comments. I didn't test it yet so there could be some errors.

    $qb = $em->createQueryBuilder();
    $qb
      ->select('a.title, a.author, count(c)')
      ->from('Article', 'a')
      ->leftJoin('a.comments', 'c')
      ->groupBy('a.id');
    
    $paginator = $this->get('knp_paginator'); 
    $pagination = $paginator->paginate($qb, $page, $limit);
    

    As I said, this issue is not really Doctrine related because your initial model design is bad. Usually, you don't need to store an aggregate which can be computed with a count/groupby query. This kind of aggregate is useful when you have a lot of joined entities which creates a real overhead during computing. Else, you don't need it.