friendsofsymfony/comment-bundle
FOSCommentBundle adds a full comment system to Symfony (3.4/4.4): threaded comment trees, embeddable threads, Doctrine ORM/MongoDB support, sortable trees, REST API via FOSRestBundle, event hooks, optional ACL, FOSUserBundle, Akismet, and markup parsing.
Install the Bundle
composer require friendsofsymfony/comment-bundle
Enable Required Bundles (Symfony 4.x config/bundles.php or Symfony 3.x AppKernel.php):
new FOS\RestBundle\FOSRestBundle(),
new FOS\CommentBundle\FOSCommentBundle(),
new JMS\SerializerBundle\JMSSerializerBundle($this),
Configure HTTP Method Override (Symfony 4.x config/packages/framework.yaml or Symfony 3.x config.yml):
framework:
http_method_override: true
Enable Translations (Symfony 4.x config/packages/framework.yaml or Symfony 3.x config.yml):
framework:
translator: ~
Create Custom Comment and Thread Entities
Extend BaseComment and BaseThread (see Step 2 docs).
Import Routing (Symfony 4.x config/routes.yaml or Symfony 3.x routing.yml):
fos_comment:
resource: "@FOSCommentBundle/Resources/config/routing.xml"
prefix: /
Enable Comments on a Page
Use the fos_comment_box Twig function in your template:
{{ fos_comment_box(thread) }}
Define a Thread Entity (e.g., BlogPostThread):
use FOS\CommentBundle\Entity\BaseThread;
class BlogPostThread extends BaseThread
{
// Add custom fields (e.g., relation to BlogPost)
}
Configure the Thread in config.yml:
fos_comment:
thread_class: App\Entity\BlogPostThread
comment_class: App\Entity\Comment
Display Comments in Twig:
{% for thread in blogPost.threads %}
{{ fos_comment_box(thread) }}
{% endfor %}
Thread entities to group comments under a specific object (e.g., blog post, product).// In a controller
$thread = $threadManager->createThread();
$thread->setObject($blogPost); // Link thread to a blog post
$threadManager->saveThread($thread);
getChildren() and getParent() on Comment entities.{% for comment in thread.comments %}
<div class="comment">
{{ comment.body }}
{% if comment.children|length > 0 %}
<div class="replies">
{% for reply in comment.children %}
{{ fos_comment_box(reply) }}
{% endfor %}
</div>
{% endif %}
</div>
{% endfor %}
fos_comment_form Twig function to render a comment form tied to a thread.{{ form_start(fos_comment_form(thread)) }}
{{ form_widget(form.body) }}
{{ form_widget(form.author) }}
<button type="submit">Post Comment</button>
{{ form_end(fos_comment_form(thread)) }}
FOSRestBundle to expose comment endpoints. Configure routes in routing.yml:
fos_comment_rest:
resource: "@FOSCommentBundle/Resources/config/routing/rest.xml"
prefix: /api
GET /api/comments/{threadId}: Fetch comments for a thread.POST /api/comments: Create a new comment.fos_comment_post, fos_comment_delete) to extend functionality.// src/EventListener/CommentListener.php
use FOS\CommentBundle\Event\CommentEvent;
class CommentListener
{
public function onCommentPost(CommentEvent $event)
{
$comment = $event->getComment();
// Send notification email, log comment, etc.
}
}
Register the listener in services.yaml:
services:
App\EventListener\CommentListener:
tags:
- { name: kernel.event_listener, event: fos_comment_post, method: onCommentPost }
Comment and Thread entities extend the correct base classes:
use FOS\CommentBundle\Model\BaseComment;
use FOS\CommentBundle\Model\BaseThread;
MarkdownExtraParser) and set it in config.yml:
fos_comment:
service:
markup: markup.markdown_extra
Vote class to implement SignedVoteInterface for user-specific votes.SortingInterface for custom sorting logic (e.g., by popularity):
services:
app.comment.sorter.popularity:
class: App\Sorting\PopularitySorting
tags:
- { name: fos_comment.sorter, alias: popularity }
Configure in config.yml:
fos_comment:
service:
sorting:
default: popularity
fos_comment.js bundle asset for AJAX comment submission and real-time updates.$(document).ready(function() {
$('.comment-form').fosCommentForm();
});
Thread to an object (e.g., BlogPost) will result in orphaned threads.$thread->setObject($blogPost);
HtmlPurifier) can lead to XSS vulnerabilities or broken rendering.exercise_html_purifier:
default:
config:
HTML.Allowed: 'p[style], em, strong, a[href], ul, ol, li'
Thread or Comment entities directly can cause stale data if not invalidated properly.fos_comment.manager to refresh entities:
$threadManager = $this->get('fos_comment.manager');
$thread = $threadManager->findThreadByObject($blogPost);
tags:
- { name: kernel.event_listener, event: fos_comment_post, method: onCommentPost, priority: 10 }
@PrePersist or @PreUpdate on Comment/Thread entities can conflict with FOSCommentBundle’s lifecycle.public function onCommentEvent(GenericEvent $event)
{
error_log('Event: ' . $event->getName());
}
commentable_object and commentable_type fields exist in the fos_comment_thread table for object linking.How can I help you explore Laravel packages today?