Im building a blog in Symfony2, it has two entities: Blog
and BlogComment
(this is a simplified example). The Blog
has an OneToMany relation with BlogComment
. When a BlogComment
is posted the property published
is set to false
. After the admin approved the BlogComment
, it is set to true
.
I want to create an overview with all my Blog
-posts and show the number of BlogComment
that are published = true
and published = false
in two seperate fields. It is possible to put all the BlogComment
in a loop and count, but as it can be an very large overview of Blog
-posts this isn't my preferred option.
I created two properties at Blog
: published_comments_count
and unpublished_comments_count
. To update these fields, I created a listener to BlogComment
:
class BlogCommentListener
{
public function onFlush(OnFlushEventArgs $args)
{
$em = $args->getEntityManager();
$uow = $em->getUnitOfWork();
$entities = array_merge(
$uow->getScheduledEntityInsertions(),
$uow->getScheduledEntityUpdates(),
$uow->getScheduledEntityDeletions()
);
foreach($entities as $entity){
if($entity instanceof BlogComment){
$Blog = $entity->getBlog();
$published_comments_count = 0;
$unpublished_comments_count = 0;
foreach($Blog->getComments() as $BlogComment){
if($BlogComment->getPublished()){
$published_comments_count++;
} else {
$unpublished_comments_count++;
}
}
$Blog->setPublishedCommentsCount($published_comments_count);
$Blog->setUnpublishedCommentsCount($unpublished_comments_count);
$em->persist($Blog);
$md = $em->getClassMetadata(get_class($Blog));
$uow->recomputeSingleEntityChangeSet($md, $Blog);
}
}
}
}
It works pretty well, but when I add a new comment, it is not in the ArrayCollection of $Blog->getComments()
yet. Is there a way to compute the changes in this ArrayCollection?
I don't think it's possible to compute the changes in the arrayCollection but you can change your logic By adding or removing 1 for each your entity :
class BlogCommentListener
{
public function onFlush(OnFlushEventArgs $args)
{
$em = $args->getEntityManager();
$uow = $em->getUnitOfWork();
$insertions = $uow->getScheduledEntityInsertions();
$deletions = $uow->getScheduledEntityDeletions();
foreach($insertions as $entity){
if($entity instanceof BlogComment){
$Blog = $entity->getBlog();
$Blog->setUnpublishedCommentsCount($Blog->getUnpublishedCommentsCount()+1);//Here the comment inserted must be unpublished
$em->persist($Blog);
$md = $em->getClassMetadata(get_class($Blog));
$uow->recomputeSingleEntityChangeSet($md, $Blog);
}
}
}
foreach($deletions as $entity){
if($entity instanceof BlogComment) {
$Blog = $entity->getBlog();
if ($entity->getPublished()) {
$Blog->setPublishedCommentsCount($Blog->getPublishedCommentsCount()-1);//Here the comment inserted must be unpublished
} else {
$Blog->setUnpublishedCommentsCount($Blog->getUnpublishedCommentsCount()-1);
}
$em->persist($Blog);
$md = $em->getClassMetadata(get_class($Blog));
$uow->recomputeSingleEntityChangeSet($md, $Blog);
}
}
}
And in bonus, i'll purpose to you a solution easier : Use the count filter in your twig template :
{% for blog in blogs %}
<li><h4>blog.title</h4>
<p>comments published : {{ blog.comments.published|count }}</p>
<p>comments non-published : {{ (not blog.comments.published)|count }}</p>
{% endfor %}