đ€ CQRS
Introductionâ
CQRS (Command Query Responsibility Segregation) est un modĂšle d'architecture qui sĂ©pare les responsabilitĂ©s des commandes et des requĂȘtes. L'idĂ©e principale est d'utiliser un modĂšle diffĂ©rent pour les opĂ©rations d'Ă©criture (commandes) et de lecture (requĂȘtes). Cette approche peut ĂȘtre utile dans des situations complexes, bien que pour la plupart des systĂšmes, CQRS puisse introduire une certaine complexitĂ© supplĂ©mentaire.
Pour plus d'informations sur CQRS, consultez cet article.
Installationâ
Ajoutez le package CQRS Ă votre projet avec la commande suivante :
composer require bowphp/cqrs
Utilisation des commandes (Command)â
Les commandes sont utilisées pour effectuer des opérations d'écriture ou des actions qui modifient l'état de votre systÚme.
Ătape 1 : CrĂ©er une commandeâ
Créez une commande en implémentant l'interface Bow\CQRS\Command\CommandInterface
. Par exemple, pour créer un utilisateur :
use Bow\CQRS\Command\CommandInterface;
class CreateUserCommand implements CommandInterface
{
public function __construct(
public string $username,
public string $email
) {}
}
Ătape 2 : CrĂ©er un handler pour la commandeâ
Créez un handler qui exécutera la logique associée à la commande. Ce handler doit implémenter l'interface Bow\CQRS\Command\CommandHandlerInterface
:
use Bow\CQRS\Command\CommandHandlerInterface;
class CreateUserCommandHandler implements CommandHandlerInterface
{
public function __construct(public UserService $userService) {}
public function process(CommandInterface $command): mixed
{
if ($this->userService->exists($command->email)) {
throw new UserServiceException(
"The user already exists"
);
}
return $this->userService->create([
"username" => $command->username,
"email" => $command->email
]);
}
}
Ătape 3 : Enregistrer la commande et son handlerâ
Ajoutez la commande et son handler dans le registre des commandes dans App\Configurations\ApplicationConfiguration::class
:
use Bow\CQRS\Registration as CQRSRegistration;
public function run()
{
CQRSRegistration::commands([
CreateUserCommand::class => CreateUserCommandHandler::class
]);
}
Ătape 4 : ExĂ©cuter la commande dans un contrĂŽleurâ
Dans un contrĂŽleur, utilisez le CommandBus
pour exécuter la commande :
namespace App\Controllers;
use Bow\CQRS\Command\CommandBus;
use App\Controllers\Controller;
use App\Commands\CreateUserCommand;
class UserController extends Controller
{
public function __construct(private CommandBus $commandBus) {}
public function __invoke(Request $request)
{
$payload = $request->only(['username', 'email']);
$command = new CreateUserCommand(
$payload['username'],
$payload['email']
);
$result = $this->commandBus->execute($command);
return redirect()
->back()
->withFlash("message", "User created");
}
}
Ajoutez une route pour appeler cette méthode :
$app->post("/users/create", UserController::class);
Utilisation des requĂȘtes (Query)â
Les requĂȘtes sont utilisĂ©es pour rĂ©cupĂ©rer des donnĂ©es sans modifier l'Ă©tat de votre systĂšme.
Ătape 1 : CrĂ©er une requĂȘteâ
CrĂ©ez une requĂȘte en implĂ©mentant l'interface Bow\CQRS\Query\QueryInterface
. Par exemple, pour récupérer un utilisateur par son ID :
use Bow\CQRS\Query\QueryInterface;
class GetUserByIdQuery implements QueryInterface
{
public function __construct(public int $userId) {}
}
Ătape 2 : CrĂ©er un handler pour la requĂȘteâ
Créez un handler pour exécuter la logique de récupération des données. Ce handler doit implémenter l'interface Bow\CQRS\Query\QueryHandlerInterface
:
use Bow\CQRS\Query\QueryHandlerInterface;
class GetUserByIdQueryHandler implements QueryHandlerInterface
{
public function __construct(public UserService $userService) {}
public function process(QueryInterface $query): mixed
{
return $this->userService->findById($query->userId);
}
}
Ătape 3 : Enregistrer la requĂȘte et son handlerâ
Ajoutez la requĂȘte et son handler dans le registre des requĂȘtes dans App\Configurations\ApplicationConfiguration::class
:
use Bow\CQRS\Registration as CQRSRegistration;
public function run()
{
CQRSRegistration::queries([
GetUserByIdQuery::class => GetUserByIdQueryHandler::class
]);
}
Ătape 4 : ExĂ©cuter la requĂȘte dans un contrĂŽleurâ
Dans un contrĂŽleur, utilisez le QueryBus
pour exĂ©cuter la requĂȘte :
namespace App\Controllers;
use Bow\CQRS\Query\QueryBus;
use App\Controllers\Controller;
use App\Queries\GetUserByIdQuery;
class UserController extends Controller
{
public function __construct(private QueryBus $queryBus) {}
public function show(int $userId)
{
$query = new GetUserByIdQuery($userId);
$user = $this->queryBus->execute($query);
return view("user.profile", ["user" => $user]);
}
}
Ajoutez une route pour appeler cette méthode :
$app->get("/users/{id}", [UserController::class, 'show']);
Avec CQRS, vous pouvez structurer vos applications pour séparer clairement les préoccupations entre la lecture et l'écriture, tout en conservant un code organisé et maintenable.
Il manque quelque chose ?
Si vous rencontrez des problÚmes avec la documentation ou si vous avez des suggestions pour améliorer la documentation ou le projet en général, veuillez déposer une issue pour nous, ou envoyer un tweet mentionnant le compte Twitter @bowframework ou sur directement sur le github.