Query bus in Symfony application

In the previous post, we created a simple command bus. This time we are going to focus on query bus. Contrary to commands, queries return a value and don’t change the state of the system. The codebase for this post is available here.

Bus configuration

Let’s get started with the configuration of the bus. We don’t need to add any middleware this time.

// config/packages/messenger.yaml

messenger:
    default_bus: command.bus
    buses:
        command.bus:
            middleware:
                - doctrine_transaction
        query.bus: ~

And restrict query handlers to be available only for the query bus.

// config/services.yaml

services:
    // ...
    App\Query\Handler\:
        autoconfigure: false
        resource: '../src/Query/Handler'
        tags: [{ name: messenger.message_handler, bus: query.bus }]

Query and query handler

We want to retrieve all of the notes stored in a database so we don’t need to implement any parameters in our query.

// src/Query/GetAllNotes.php

<?php
namespace App\Query;

class GetAllNotes
{

}
// src/Query/Handler/GetAllNotesHandler.php

<?php
namespace App\Query\Handler;

use App\Query\GetAllNotes;
use App\Repository\NoteRepository;
use Symfony\Component\Messenger\Handler\MessageHandlerInterface;

class GetAllNotesHandler implements MessageHandlerInterface
{
    private $notes;

    public function __construct(NoteRepository $noteRepository)
    {
        $this->notes = $noteRepository;
    }

    public function __invoke(GetAllNotes $query)
    {
        return $this->notes->findAll();
    }
}

Now we can finally implement index action of IndexCotroller and make our application work.

// src/Controller/IndexController.php

<?php
namespace App\Controller;

use App\Query\GetAllNotes;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Messenger\Stamp\HandledStamp;
use Symfony\Component\Routing\Annotation\Route;

class IndexController extends AbstractController
{
    /**
     * @Route("/", name="index")
     */
    public function index(MessageBusInterface $queryBus)
    {
        $envelope = $queryBus->dispatch(new GetAllNotes());
        $handledStamp = $envelope->last(HandledStamp::class);
        $notes = $handledStamp->getResult();

        return $this->render("index/index.html.twig", ["notes" => $notes]);
	}
}

And that’s it! Now the home page of the application shows all notes stored in a database.

Summary

All code up to this point is available here. In the next post of the series, we are going to create an asynchronous event bus.

You May Also Like

Leave a Reply

Your email address will not be published. Required fields are marked *