Skip to content

Instantly share code, notes, and snippets.

@cierzniak
Created December 5, 2018 10:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cierzniak/febbcf46aedf991ccbb35f0e6415bda2 to your computer and use it in GitHub Desktop.
Save cierzniak/febbcf46aedf991ccbb35f0e6415bda2 to your computer and use it in GitHub Desktop.
Request Handler with Validation for PHP projects
<?php declare(strict_types=1);
namespace Api\Controller;
use Api\Model\User\TokenDTO;
use Api\RequestValidator\RequestHandler;
use Api\RequestValidator\Security\RefreshTokenRequestValidator;
use Api\RequestValidator\ValidationFailed;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
final class SampleController extends Controller
{
/**
* @Route(methods={"POST"})
*/
public function refreshTokenAction(Request $request, RequestHandler $handler): Response
{
try {
/** @var TokenDTO $dto */
$dto = $handler->handle($request, new RefreshTokenRequestValidator());
} catch (ValidationFailed $e) {
return $this->json([
'error' => [
'message' => $e->getMessage(),
'violations' => $e->getViolations(), // FIXME: Change ConstraintViolationsList to array
],
], Response::HTTP_UNPROCESSABLE_ENTITY);
}
// DO some stuff with DTO
return $this->json(['data' => true], Response::HTTP_OK);
}
}
<?php declare(strict_types=1);
namespace Api\RequestValidator;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Validator\Validator\ValidatorInterface;
class RequestHandler
{
private $validator;
public function __construct(ValidatorInterface $validator)
{
$this->validator = $validator;
}
public function handle(Request $request, RequestValidatorInterface $requestValidator): object
{
$data = $request->request->all();
$violations = $this->validator->validate($data, $requestValidator->getRules());
if ($violations->count()) {
throw new ValidationFailed($violations);
}
return $requestValidator->prepareModel($data);
}
}
<?php declare(strict_types=1);
namespace Api\RequestValidator;
use Symfony\Component\Validator\Constraints\Collection;
interface RequestValidatorInterface
{
public function getRules(): Collection;
public function prepareModel(array $data): object;
}
<?php declare(strict_types=1);
namespace Api\RequestValidator;
use Symfony\Component\Validator\ConstraintViolationListInterface;
class ValidationFailed extends \RuntimeException
{
private $violationList;
public function __construct(ConstraintViolationListInterface $violationList)
{
$this->violationList = $violationList;
parent::__construct('Validation failed.');
}
public function getViolations(): ConstraintViolationListInterface
{
return $this->violationList;
}
}
<?php declare(strict_types=1);
namespace Api\RequestValidator\Validator;
use Api\Model\TokenDTO;
use Api\RequestValidator\RequestValidatorInterface;
use Symfony\Component\Validator\Constraints as Assert;
class SampleRequestValidator implements RequestValidatorInterface
{
public function getRules(): Assert\Collection
{
return new Assert\Collection([
'token' => [
new Assert\NotBlank(),
],
]);
}
public function prepareModel(array $data): object
{
return new TokenDTO($data['token']);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment