Symfony’de Validation Response Düzenleme
Symfony’de, request tipiyle yapılan validasyonlarda hatalar genellikle symfony validator paketinde bulunan varsayılan response yapısıyla döndürülür.
Ancak bazı projelerde, validasyon hatalarının ve tüm hata mesajlarının genel bir response yapısında döndürülmesi gerekebilir. Bu durumda, özelleştirilmiş bir validasyon normalizer sınıfı oluşturarak bu hataları yönetmek mümkündür.
İlk olarak, aşağıdaki gibi bir örnek LoginRequestType sınıfı oluşturalım:
<?php
namespace App\Type;
use Symfony\Component\Validator\Constraints as Assert;
final class LoginRequestType
{
/**
* @Assert\NotBlank()
* @Assert\Type("string")
* @var string
*/
public $email;
/**
* @Assert\NotBlank()
* @Assert\Type("string")
* @var string
*/
public $password;
}
Yukarıdaki örnekte, bir login işlemi için beklenen request tipini tanımladık. Eğer email veya password gönderilmezse, Symfony validator sınıfı varsayılan olarak aşağıdaki gibi bir response yapısıyla hata döndürecektir:
{
"type": "https://symfony.com/errors/validation",
"title": "Validation Failed",
"detail": "password: Bu değer boş bırakılmamalıdır.",
"violations": [
{
"propertyPath": "password",
"title": "Bu değer boş bırakılmamalıdır.",
"parameters": {
"{{ value }}": "null"
},
"type": "urn:uuid:c1051bb4-d103-4f74-8988-acbcafc7fdc3"
}
]
}
Ancak, bu gibi durumlarda, genel bir response yapısına uygun olarak validasyon hatalarını özelleştirmek isteyebiliriz. Bu amaçla, özelleştirilmiş bir ConstraintViolationListNormalizer sınıfı oluşturmamız gerekmektedir. Aşağıda örnek bir sınıf tanımı yer almaktadır:
<?php
namespace App\Normalizer;
use App\Type\Response\GenericResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Component\Validator\ConstraintViolationListInterface;
class ConstraintViolationListNormalizer implements NormalizerInterface, CacheableSupportsMethodInterface
{
private $defaultContext;
private $nameConverter;
public function __construct(array $defaultContext = [], NameConverterInterface $nameConverter = null)
{
$this->defaultContext = $defaultContext;
$this->nameConverter = $nameConverter;
}
/**
* @param $object
* @param string|null $format
* @param array $context
* @return array|array[]
*/
public function normalize($object, string $format = null, array $context = []): array
{
$violations = [];
$messages = [];
foreach ($object as $violation) {
$propertyPath = $this->nameConverter ? $this->nameConverter->normalize($violation->getPropertyPath(), null, $format, $context) : $violation->getPropertyPath();
$violationEntry = [
'property' => $propertyPath,
'message' => $violation->getMessage()
];
$violations[] = $violationEntry;
$prefix = $propertyPath ? sprintf('%s: ', $propertyPath) : '';
$messages[] = $prefix.$violation->getMessage();
}
$response = new GenericResponse();
$response->setCode(Response::HTTP_BAD_REQUEST);
$response->setMessage(implode("\n", $messages));
$response->setErrors($violations);
return $response->toArray();
}
/**
* @param $data
* @param string|null $format
* @return bool
*/
public function supportsNormalization($data, string $format = null): bool
{
return $data instanceof ConstraintViolationListInterface;
}
/**
* @return bool
*/
public function hasCacheableSupportsMethod(): bool
{
return __CLASS__ === static::class;
}
}
Yukarıdaki örnekte, ConstraintViolationListNormalizer sınıfındaki normalize() methodu validasyon hatalarının özelleştirilmesi işlemleri gerçekleştirecektir.
Artık, bu özelleştirilmiş normalizer sınıfı, tüm validasyon hatalarında devreye girecek ve Symfony validator paketindeki normalizer sınıfını devre dışı bırakacaktır. Örneğin:
{
"code": 400,
"message": "password: Bu değer boş bırakılmamalıdır.",
"errors": [
{
"property": "password",
"message": "Bu değer boş bırakılmamalıdır."
}
]
}
Umarım bu örnek, Symfony’de validasyon hatalarının nasıl özelleştirilebileceği konusunda size yardımcı olur.
Vakit ayırıp okuduğunuz için teşekkürler, umarım yardımcı olmuşturum.