Skip to content

Issue in hexagonal implementation for the controller. #3

@ArensMyzyri

Description

@ArensMyzyri

Hey there.
In the UI web controller you are using symfony http response which goes against hexagonal architecture.
I would suggest to build a service in infrastructure where you implement the http response and then use its interface on your controller.
Example: In Domain create MyHttpResponseInterface and implement it in MySymfonyHttpResponse class (in infrastructure), then use this interface in your controller.

Here an example how I built a controller:

<?php

declare(strict_types=1);

namespace App\Product\Infrastructure\Controller;

use App\Product\Application\Query\GetProductQuery;
use App\Product\Domain\Dto\Product\ProductDto;
use App\Product\Domain\Dto\Uuid;
use App\Product\Domain\Exception\DomainExceptionInterface;
use App\Product\Domain\NormalizerAndSerializer\ModelNormalizerInterface;
use App\Product\Domain\Validator\ModelValidatorInterface;
use App\Product\Domain\Validator\JsonValidatorInterface;
use App\Shared\Domain\Bus\Query\QueryBus;
use App\Shared\Domain\Http\HttpResponseFactoryInterface;
use App\Shared\Domain\Http\HttpResponseInterface;
use App\Shared\Domain\Http\RequestInterface;
use App\Shared\Domain\Http\ResponseDataBuilderInterface;

class ProductController
{
    public function __construct(
        readonly HttpResponseFactoryInterface $httpResponseFactory,
        readonly ResponseDataBuilderInterface $responseDataBuilder,
        readonly QueryBus $queryBus,
        readonly ModelValidatorInterface $modelValidator,
        readonly ModelNormalizerInterface $normalizer,
        readonly JsonValidatorInterface $jsonValidator
    ) {}

    public function getSingle(string $productId, ?string $resourceType = null): HttpResponseInterface
    {
        try {
            $errors = $this->modelValidator->validate([new Uuid($productId)]);

            if ($errors) {
                throw new DomainBadRequestException($errors);
            }

            /** @var ProductDto $product */
            $product = $this->queryBus->ask(new GetProductQuery($productId));

            if (!$product) {
                throw new DomainNotFoundException([]);
            }
            return $this->httpResponseFactory->create(
                $this->responseDataBuilder->build($product, false, ''),
                200,
                $resourceType
            );
        } catch (DomainExceptionInterface $domainException) {
            return $this->httpResponseFactory->create(
                $this->responseDataBuilder->build($domainException->getData(), true, $domainException->getMessage()),
                $domainException->getStatusCode(),
                $resourceType
            );
        }
    }
    }

Let me know what you think :)

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions