Skip to content

Commit

Permalink
step 9: introduce the query bus
Browse files Browse the repository at this point in the history
  • Loading branch information
Antoine Lelaisant committed Nov 4, 2022
1 parent fefd6cf commit 95ccd9c
Show file tree
Hide file tree
Showing 21 changed files with 466 additions and 43 deletions.
2 changes: 2 additions & 0 deletions config/packages/messenger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ framework:
command.bus:
middleware:
- doctrine_transaction

query.bus: ~
5 changes: 5 additions & 0 deletions config/services/messenger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,8 @@ services:
Application\MessageBus\CommandBus:
alias: Infrastructure\Symfony\Messenger\CommandBus

Infrastructure\Symfony\Messenger\QueryBus:
$messageBus: '@query.bus'

Application\MessageBus\QueryBus:
alias: Infrastructure\Symfony\Messenger\QueryBus
11 changes: 11 additions & 0 deletions config/services/queries.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
services:
_defaults:
autowire: true
autoconfigure: true
public: false

Domain\Query\:
resource: '%kernel.project_dir%/src/Domain/Query/**/Handler.php'
tags:
- { name: messenger.message_handler, bus: query.bus }
34 changes: 12 additions & 22 deletions src/Application/Controller/DinosaursController.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
use Application\Form\Type\DinosaurType;
use Application\Form\Type\SearchType;
use Application\MessageBus\CommandBus;
use Domain\Collection\DinosaursCollection;
use Application\MessageBus\QueryBus;
use Domain\Exception\DinosaurNotFoundException;
use Domain\Query\GetSingleDinosaur;
use Domain\Query\GetAllDinosaurs;
use Domain\UseCase\CreateDinosaur;
use Domain\UseCase\EditDinosaur;
use Domain\UseCase\RemoveDinosaur;
Expand All @@ -18,8 +21,8 @@
class DinosaursController extends AbstractController
{
public function __construct(
private DinosaursCollection $dinosaursCollection,
private CommandBus $commandBus
private CommandBus $commandBus,
private QueryBus $queryBus
) {}

#[Route('/dinosaurs', name: 'app_list_dinosaurs')]
Expand All @@ -36,10 +39,7 @@ public function list(Request $request): Response
$q = $search['q'];
}

$dinosaurs = $this
->dinosaursCollection
->search($q)
;
$dinosaurs = $this->queryBus->dispatch(new GetAllDinosaurs\Query($q));

return $this->render('dinosaurs-list.html.twig', [
'dinosaurs' => $dinosaurs,
Expand Down Expand Up @@ -111,32 +111,22 @@ public function create(Request $request): Response
)]
public function edit(Request $request, int $id): Response
{
$dinosaur = $this
->dinosaursCollection
->find($id)
;

if ($dinosaur === false) {
try {
$dinosaur = $this->queryBus->dispatch(new GetSingleDinosaur\Query($id));
} catch (DinosaurNotFoundException $e) {
throw $this->createNotFoundException(
'The dinosaur you are looking for does not exists.'
);
}

$form = $this->createForm(DinosaurType::class, $dinosaur->toArray());
$form = $this->createForm(DinosaurType::class, $dinosaur);

$form->handleRequest($request);

if ($form->isSubmitted() && $form->isValid()) {
$dinosaur = $form->getData();

$input = new EditDinosaur\Input(
$id,
$dinosaur['name'],
$dinosaur['gender'],
$dinosaur['species']->getId(),
$dinosaur['age'],
$dinosaur['eyesColor']
);
$input = EditDinosaur\Input::fromReadModel($dinosaur);

try {
$this->commandBus->dispatch($input);
Expand Down
33 changes: 12 additions & 21 deletions src/Application/Controller/SpeciesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@

use Application\Form\Type\SpeciesType;
use Application\MessageBus\CommandBus;
use Domain\Collection\SpeciesCollection;
use Application\MessageBus\QueryBus;
use Domain\Exception\SpeciesAlreadyExistsException;
use Domain\Exception\SpeciesNotFoundException;
use Domain\Query\GetAllSpecies;
use Domain\Query\GetSingleSpecies;
use Domain\UseCase\CreateSpecies;
use Domain\UseCase\EditSpecies;
use Domain\UseCase\RemoveSpecies;
Expand All @@ -20,19 +22,16 @@
class SpeciesController extends AbstractController
{
public function __construct(
private SpeciesCollection $speciesCollection,
private CommandBus $commandBus
private CommandBus $commandBus,
private QueryBus $queryBus
)
{
}

#[Route('/species', name: 'app_list_species')]
public function list(): Response
{
$speciesList = $this
->speciesCollection
->findAll()
;
$speciesList = $this->queryBus->dispatch(new GetAllSpecies\Query());

return $this->render('species-list.html.twig', [
'speciesList' => $speciesList
Expand Down Expand Up @@ -78,29 +77,21 @@ public function create(Request $request): Response
)]
public function edit(Request $request, string $id): Response
{
$species = $this
->speciesCollection
->find($id)
;

if ($species === false) {
try {
$species = $this->queryBus->dispatch(new GetSingleSpecies\Query($id));
} catch (SpeciesNotFoundException $e) {
throw $this->createNotFoundException(
'The species you are looking for does not exists.'
);
}

$form = $this->createForm(SpeciesType::class, $species->toArray());
$form = $this->createForm(SpeciesType::class, $species);
$form->handleRequest($request);

if ($form->isSubmitted() && $form->isValid()) {
$rawSpecies = $form->getData();
$species = $form->getData();

$input = new EditSpecies\Input(
speciesId: $id,
name: $rawSpecies['name'],
habitats: $rawSpecies['habitats'],
feeding: $rawSpecies['feeding']
);
$input = EditSpecies\Input::fromReadModel($species);

try {
$this->commandBus->dispatch($input);
Expand Down
45 changes: 45 additions & 0 deletions src/Application/Form/DataTransformer/SpeciesReadToModel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

declare(strict_types=1);

namespace Application\Form\DataTransformer;

use Domain\Collection\SpeciesCollection;
use Domain\Exception\SpeciesNotFoundException;
use Domain\Model\Species as ModelSpecies;
use Domain\ReadModel\Species;
use Symfony\Component\Form\DataTransformerInterface;

class SpeciesReadToModel implements DataTransformerInterface
{
public function __construct(
private SpeciesCollection $speciesCollection
) {
}

public function transform(mixed $value)
{
if (!$value instanceof Species) {
return $value;
}

$speciesId = (string) $value->getId();

$species = $this->speciesCollection->find($speciesId);

if ($species === null) {
throw new SpeciesNotFoundException($speciesId);
}

return $species;
}

public function reverseTransform(mixed $value)
{
if (!$value instanceof ModelSpecies) {
return $value;
}

return new Species($value);
}
}
8 changes: 8 additions & 0 deletions src/Application/Form/Type/DinosaurType.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Application\Form\Type;

use Application\Form\DataTransformer\SpeciesReadToModel;
use Domain\Model\Species;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
Expand All @@ -13,6 +14,11 @@

class DinosaurType extends AbstractType
{
public function __construct(
private SpeciesReadToModel $speciesReadToModel
) {
}

public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
Expand All @@ -31,5 +37,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
->add('eyesColor', ColorType::class)
->add('submit', SubmitType::class)
;

$builder->get('species')->addModelTransformer($this->speciesReadToModel);
}
}
10 changes: 10 additions & 0 deletions src/Application/MessageBus/QueryBus.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

namespace Application\MessageBus;

interface QueryBus
{
public function dispatch(object $input): mixed;
}
27 changes: 27 additions & 0 deletions src/Domain/Query/GetAllDinosaurs/Handler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace Domain\Query\GetAllDinosaurs;

use Domain\Collection\DinosaursCollection;
use Domain\Model\Dinosaur as ModelDinosaur;
use Domain\ReadModel\Dinosaur;

class Handler
{
public function __construct(
private DinosaursCollection $dinosaursCollection
) {
}

public function __invoke(Query $query): array
{
$dinosaurs = $this->dinosaursCollection->search($query->search);

return array_map(
fn (ModelDinosaur $dinosaur) => new Dinosaur($dinosaur),
$dinosaurs
);
}
}
13 changes: 13 additions & 0 deletions src/Domain/Query/GetAllDinosaurs/Query.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

declare(strict_types=1);

namespace Domain\Query\GetAllDinosaurs;

final class Query
{
public function __construct(
public readonly ?string $search = null
) {
}
}
27 changes: 27 additions & 0 deletions src/Domain/Query/GetAllSpecies/Handler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace Domain\Query\GetAllSpecies;

use Domain\Collection\SpeciesCollection;
use Domain\Model\Species as ModelSpecies;
use Domain\ReadModel\Species;

class Handler
{
public function __construct(
private SpeciesCollection $speciesCollection
) {
}

public function __invoke(Query $query): array
{
$species = $this->speciesCollection->findAll();

return array_map(
fn (ModelSpecies $species) => new Species($species),
$species
);
}
}
12 changes: 12 additions & 0 deletions src/Domain/Query/GetAllSpecies/Query.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Domain\Query\GetAllSpecies;

final class Query
{
public function __construct(
) {
}
}
28 changes: 28 additions & 0 deletions src/Domain/Query/GetSingleDinosaur/Handler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace Domain\Query\GetSingleDinosaur;

use Domain\Collection\DinosaursCollection;
use Domain\Exception\DinosaurNotFoundException;
use Domain\ReadModel\Dinosaur;

class Handler
{
public function __construct(
private DinosaursCollection $dinosaursCollection
) {
}

public function __invoke(Query $query): Dinosaur
{
$dinosaur = $this->dinosaursCollection->find($query->id);

if ($dinosaur === null) {
throw new DinosaurNotFoundException($query->id);
}

return new Dinosaur($dinosaur);
}
}
13 changes: 13 additions & 0 deletions src/Domain/Query/GetSingleDinosaur/Query.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

declare(strict_types=1);

namespace Domain\Query\GetSingleDinosaur;

final class Query
{
public function __construct(
public readonly string $id,
) {
}
}
Loading

0 comments on commit 95ccd9c

Please sign in to comment.