Installation
Add the bundle to your composer.json:
composer require darles/forum-bundle
Enable it in config/bundles.php:
Darles\ForumBundle\DarlesForumBundle::class => ['all' => true],
Database Migration Run migrations (if provided) via Doctrine:
php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrate
Note: Check src/Darles/ForumBundle/Resources/config/doctrine/ for schema definitions.
First Use Case Create a basic forum controller:
use Darles\ForumBundle\Controller\ForumController;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class MyForumController extends AbstractController
{
public function index(ForumController $forumController)
{
return $forumController->listForums();
}
}
Route it in config/routes.yaml:
forum_index:
path: /forum
controller: App\Controller\MyForumController::index
Key Configuration
Override default settings in config/packages/darles_forum.yaml:
darles_forum:
default_category: 'General'
posts_per_page: 20
Forum Structure
Forum (belongs to Category)Thread (belongs to Forum)Post (belongs to Thread or Thread itself for the first post).$category = $this->getDoctrine()->getRepository(Category::class)->findOneBy(['slug' => 'general']);
$forum = $category->getForums()->first();
$thread = $forum->getThreads()->first();
CRUD Operations
$thread = new Thread();
$thread->setTitle('New Thread')
->setForum($forum)
->setContent('Hello!');
$entityManager->persist($thread);
$entityManager->flush();
$post = new Post();
$post->setThread($thread)
->setContent('Reply content')
->setAuthor($this->getUser());
$entityManager->persist($post);
Twig Integration
forum Twig functions:
{% for forum in forums %}
<h2>{{ forum.title }}</h2>
<ul>
{% for thread in forum.threads %}
<li>
<a href="{{ path('forum_thread', {'id': thread.id}) }}">
{{ thread.title }}
</a>
({{ thread.posts|length }} replies)
</li>
{% endfor %}
</ul>
{% endfor %}
Event Listeners
ThreadCreatedEvent):
use Darles\ForumBundle\Event\ThreadCreatedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class MyForumSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
ThreadCreatedEvent::NAME => 'onThreadCreated',
];
}
public function onThreadCreated(ThreadCreatedEvent $event)
{
// Send notification, log, etc.
}
}
Form Handling
$form = $this->createForm(ThreadType::class, $thread);
// or
$form = $this->createForm(PostType::class, $post);
Security
# config/packages/security.yaml
access_control:
- { path: ^/forum, roles: ROLE_USER }
- { path: ^/forum/create, roles: ROLE_ADMIN }
ForumVoter for fine-grained permissions:
$this->denyAccessUnlessGranted('VIEW', $forum);
API Endpoints
use Symfony\Component\Serializer\SerializerInterface;
$threadData = $serializer->serialize($thread, 'json', [
'groups' => ['forum_api'],
]);
Customization
templates/darles_forum/ to extend default views.views counter to Thread):
// src/Entity/Thread.php
/**
* @ORM\Column(type="integer")
*/
private $views = 0;
Testing
ForumBundleTest fixtures or create your own:
$forum = $this->createForum(['title' => 'Test Forum']);
$thread = $this->createThread(['forum' => $forum, 'title' => 'Test Thread']);
Doctrine Schema Mismatch
src/Darles/ForumBundle/Resources/config/doctrine/ for schema definitions.Deprecated Symfony 2.3
make:controller) won’t work. Use:
php bin/console generate:controller
symfony/flex recipes cautiously; this bundle predates Flex.Missing Documentation
src/Darles/ForumBundle/Controller/ForumController.phpsrc/Darles/ForumBundle/Form/Type/ThreadType.phpsrc/Darles/ForumBundle/Entity/Event Dispatching
$event = new ThreadCreatedEvent($thread);
$this->get('event_dispatcher')->dispatch($event);
Translation Keys
translations/messages.en.yml. Override in your bundle’s translations/ directory.Enable Debug Mode
# config/packages/dev/doctrine.yaml
doctrine:
dbal:
logging: true
profiling: true
Check Entity States
debug:container to inspect services:
php bin/console debug:container darles_forum
var_dump($entity->getId()) or dd($entity).Common Issues
forum_* routes are loaded in config/routes.yaml.{{ form_start(form, {'attr': {'novalidate': 'novalidate'}}) }}
Custom Fields
Thread or Post entities:
// src/Entity/Thread.php
/**
* @ORM\Column(type="string", nullable=true)
*/
private $customField;
Plugins
PostAttachment entity).ThreadPoll entity).Validation
use Symfony\Component\Validator\Constraints as Assert;
/**
* @Assert\Length(min=10)
*/
private $content;
Caching
$cache = $this->get('cache.app');
$forums = $cache->get('forum_list', function() {
return $this->getDoctrine()->getRepository(Forum::class)->findAll();
});
Testing Extensions
$this->container->set('darles_forum.mailer', $this->createMock(MailerInterface::class));
How can I help you explore Laravel packages today?