Symfony "Type" 约束:"string" 类型的预期参数,"array" 给定异常
Symfony "Type" constraint: Expected argument of type "string", "array" given exception
我有一个表格。例如,它的登录表单:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('phone', TextType::class, [
'constraints' => [
new NotBlank(),
new Type(['type' => 'string']),
new Length(['max' => 255]),
new ValueExistsInEntity([
'entityClass' => User::class,
'field' => 'phone',
'message' => 'User not found'
])
]
]);
$builder->add('password', TextType::class, [
'constraints' => [
new NotBlank(),
new Type(['type' => 'string']),
new Length(['min' => 8, 'max' => 128])
]
]);
}
如您所见,它具有 Length
约束。当我将数组发送到表单中的任何字段时,Length
约束会抛出 Symfony\Component\Validator\Exception\UnexpectedTypeException
和 500 状态代码以及消息:
Expected argument of type "string", "array" given
有什么方法可以避免这种情况或将这种异常转化为表单验证错误?
因为 Length
仅是字符串的验证器。对于数组,您必须使用 Count
验证器。
如果您想在同一个验证器中同时使用数组和字符串,您应该实现自己的 Custom validator。
我找到的唯一解决方案是创建事件侦听器,它将异常简单地转换为美丽错误(这对我来说没问题,因为我只开发 API,而不是完整堆栈)。
我的异常事件侦听器的简化部分:
namespace AppBundle\EventListener;
use AppBundle\Exceptions\FormValidationException;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\Validator\Exception\ValidatorException;
class ApiExceptionListener
{
/**
* @var bool
*/
public $isKernelDebug;
public function __construct(bool $isKernelDebug)
{
$this->isKernelDebug = $isKernelDebug;
}
public function onKernelException(GetResponseForExceptionEvent $event)
{
$throwedException = $event->getException();
$errorBody = [
'code' => $throwedException->getCode(),
'message' => $throwedException->getMessage(),
];
if ($throwedException instanceof ValidatorException) {
$errorBody['message'] = 'Invalid data has been sent';
}
if ($this->isKernelDebug) {
$errorBody['exception'] = [
'class' => get_class($throwedException),
'message' => $throwedException->getMessage(),
'code' => $throwedException->getCode(),
];
}
$event->setResponse(new JsonResponse(['error' => $errorBody]));
}
}
服务:
app.event_listener.api_exception:
class: AppBundle\EventListener\ApiExceptionListener
arguments: ['%%kernel.debug%%']
tags:
- { name: kernel.event_listener, event: kernel.exception, method: onKernelException, priority: 200 }
但我很高兴看到更好的解决方案来处理 Symfony 约束抛出的异常。
我有一个表格。例如,它的登录表单:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('phone', TextType::class, [
'constraints' => [
new NotBlank(),
new Type(['type' => 'string']),
new Length(['max' => 255]),
new ValueExistsInEntity([
'entityClass' => User::class,
'field' => 'phone',
'message' => 'User not found'
])
]
]);
$builder->add('password', TextType::class, [
'constraints' => [
new NotBlank(),
new Type(['type' => 'string']),
new Length(['min' => 8, 'max' => 128])
]
]);
}
如您所见,它具有 Length
约束。当我将数组发送到表单中的任何字段时,Length
约束会抛出 Symfony\Component\Validator\Exception\UnexpectedTypeException
和 500 状态代码以及消息:
Expected argument of type "string", "array" given
有什么方法可以避免这种情况或将这种异常转化为表单验证错误?
因为 Length
仅是字符串的验证器。对于数组,您必须使用 Count
验证器。
如果您想在同一个验证器中同时使用数组和字符串,您应该实现自己的 Custom validator。
我找到的唯一解决方案是创建事件侦听器,它将异常简单地转换为美丽错误(这对我来说没问题,因为我只开发 API,而不是完整堆栈)。
我的异常事件侦听器的简化部分:
namespace AppBundle\EventListener;
use AppBundle\Exceptions\FormValidationException;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\Validator\Exception\ValidatorException;
class ApiExceptionListener
{
/**
* @var bool
*/
public $isKernelDebug;
public function __construct(bool $isKernelDebug)
{
$this->isKernelDebug = $isKernelDebug;
}
public function onKernelException(GetResponseForExceptionEvent $event)
{
$throwedException = $event->getException();
$errorBody = [
'code' => $throwedException->getCode(),
'message' => $throwedException->getMessage(),
];
if ($throwedException instanceof ValidatorException) {
$errorBody['message'] = 'Invalid data has been sent';
}
if ($this->isKernelDebug) {
$errorBody['exception'] = [
'class' => get_class($throwedException),
'message' => $throwedException->getMessage(),
'code' => $throwedException->getCode(),
];
}
$event->setResponse(new JsonResponse(['error' => $errorBody]));
}
}
服务:
app.event_listener.api_exception:
class: AppBundle\EventListener\ApiExceptionListener
arguments: ['%%kernel.debug%%']
tags:
- { name: kernel.event_listener, event: kernel.exception, method: onKernelException, priority: 200 }
但我很高兴看到更好的解决方案来处理 Symfony 约束抛出的异常。