Symfony 表单:如何准确知道哪个字段导致错误
Symfony form: how to know precisely which field cause an error
我必须解决一个关于 Symfony 表单验证的问题,它由 30 个子表单组成,每个子表单由 3 个实体组成,每个实体有大约 20-25 个字段。所以这个单一的表格包含超过1800个字段:-(.
在验证时,编写这种丑陋表单的开发人员会像这样在一行中检查它:
if ($form->isValid()) {
[...]
}
如果表单无效,在 twig 模板中,他只写:
{{ form_errors(form) }}
因此,如果我使用当前值加载表单,并在不进行任何修改的情况下提交,验证将失败,并重复两次相同的 Symfony 默认消息:
This value should not be blank.
This value should not be blank.
但我不知道 1800 多个字段中的哪个字段导致错误,而且我没有找到如何向 Symfony 询问给定错误,即导致错误的字段。
我怎么知道哪个字段导致了错误?
编辑:我听从了亚历山大的建议并且:
$errors = $form->getErrors() ;
foreach($errors as $key => $error) {
var_dump($error);
}
只给了我两次:
class Symfony\Component\Form\FormError#1750 (3) {
protected $messageTemplate => string(31) "This value should not be blank."
protected $messageParameters => array(0) {}
protected $messagePluralization => NULL
}
不知道它发生在哪里。
在
上创建一个 foreach
$form
参见 \vendor\symfony\symfony\src\Symfony\Component\Form\Form。php -> getErrors
示例:
foreach ($form as $child) {
/** @var FormInterface $child */
if ($child->isSubmitted() && $child->isValid()) {
continue;
}
$iterator = $child->getErrors(true, $flatten);
if (0 === count($iterator)) {
continue;
}
$child->getName(); // here is the name of field
if ($flatten) {
foreach ($iterator as $error) {
$errors[] = $error;
}
} else {
$errors[] = $iterator;
}
var_dump($errors); // here are the errors of that field
}
我很久以前在网上的某个地方发现了这个方法,我每天都在使用它:)
/**
* @param FormInterface $form
*
* @return array
*/
public function getErrorsFromForm(FormInterface $form)
{
$errors = [];
foreach ($form->getErrors() as $key => $error) {
$template = $error->getMessageTemplate();
$parameters = $error->getMessageParameters();
foreach ($parameters as $var => $value) {
$template = str_replace($var, $value, $template);
}
$errors[$key] = $template;
}
foreach ($form->all() as $childForm) {
if ($childForm instanceof FormInterface) {
if ($childErrors = $this->getErrorsFromForm($childForm)) {
$errors[$childForm->getName()] = $childErrors;
}
}
}
return $errors;
}
也许它可以帮助您调试错误。
编辑:这是原始 SO 问题 Get all errors along with fields the error is connected to
您可以使用 XDEBUG 并查看 $failed
变量中的错误。
我不会准确回答你的问题,即使我明白你想要什么和你想做什么,我也会建议你另一种(也许更好)的方式。
你的错误信息This value should not be blank
是不是Symfony的默认错误信息,它是Doctrine默认的注释错误信息@Assert\NotBlank
。当然,您可以为实体上使用的每个字段自定义此错误消息。只需以这种方式在括号中添加您的消息:
/**
* @var \DateTime $startDate
*
* @Assert\NotBlank(message="The start date should not be blank/is mandatory.")
* @ORM\Column(name="startDate", type="date", nullable = false)
*/
private $startDate;
我知道您正在处理其他人的代码,有很多实体和字段,但如果您花时间替换大部分默认消息,现在和以后都可以为您节省很多时间。
对于 Symfony 4.x+(可能适用于较低版本)。
// $form = $this->createForm(SomeType::class);
// $form->submit($data);
// if (!$form->isValid()) {
// var_dump($this->getErrorsFromForm($form));
// }
private function getErrorsFromForm(FormInterface $form, bool $child = false): array
{
$errors = [];
foreach ($form->getErrors() as $error) {
if ($child) {
$errors[] = $error->getMessage();
} else {
$errors[$error->getOrigin()->getName()][] = $error->getMessage();
}
}
foreach ($form->all() as $childForm) {
if ($childForm instanceof FormInterface) {
if ($childErrors = $this->getErrorsFromForm($childForm, true)) {
$errors[$childForm->getName()] = $childErrors;
}
}
}
return $errors;
}
我必须解决一个关于 Symfony 表单验证的问题,它由 30 个子表单组成,每个子表单由 3 个实体组成,每个实体有大约 20-25 个字段。所以这个单一的表格包含超过1800个字段:-(.
在验证时,编写这种丑陋表单的开发人员会像这样在一行中检查它:
if ($form->isValid()) {
[...]
}
如果表单无效,在 twig 模板中,他只写:
{{ form_errors(form) }}
因此,如果我使用当前值加载表单,并在不进行任何修改的情况下提交,验证将失败,并重复两次相同的 Symfony 默认消息:
This value should not be blank.
This value should not be blank.
但我不知道 1800 多个字段中的哪个字段导致错误,而且我没有找到如何向 Symfony 询问给定错误,即导致错误的字段。
我怎么知道哪个字段导致了错误?
编辑:我听从了亚历山大的建议并且:
$errors = $form->getErrors() ;
foreach($errors as $key => $error) {
var_dump($error);
}
只给了我两次:
class Symfony\Component\Form\FormError#1750 (3) {
protected $messageTemplate => string(31) "This value should not be blank."
protected $messageParameters => array(0) {}
protected $messagePluralization => NULL
}
不知道它发生在哪里。
在
上创建一个 foreach$form
参见 \vendor\symfony\symfony\src\Symfony\Component\Form\Form。php -> getErrors
示例:
foreach ($form as $child) {
/** @var FormInterface $child */
if ($child->isSubmitted() && $child->isValid()) {
continue;
}
$iterator = $child->getErrors(true, $flatten);
if (0 === count($iterator)) {
continue;
}
$child->getName(); // here is the name of field
if ($flatten) {
foreach ($iterator as $error) {
$errors[] = $error;
}
} else {
$errors[] = $iterator;
}
var_dump($errors); // here are the errors of that field
}
我很久以前在网上的某个地方发现了这个方法,我每天都在使用它:)
/**
* @param FormInterface $form
*
* @return array
*/
public function getErrorsFromForm(FormInterface $form)
{
$errors = [];
foreach ($form->getErrors() as $key => $error) {
$template = $error->getMessageTemplate();
$parameters = $error->getMessageParameters();
foreach ($parameters as $var => $value) {
$template = str_replace($var, $value, $template);
}
$errors[$key] = $template;
}
foreach ($form->all() as $childForm) {
if ($childForm instanceof FormInterface) {
if ($childErrors = $this->getErrorsFromForm($childForm)) {
$errors[$childForm->getName()] = $childErrors;
}
}
}
return $errors;
}
也许它可以帮助您调试错误。
编辑:这是原始 SO 问题 Get all errors along with fields the error is connected to
您可以使用 XDEBUG 并查看 $failed
变量中的错误。
我不会准确回答你的问题,即使我明白你想要什么和你想做什么,我也会建议你另一种(也许更好)的方式。
你的错误信息This value should not be blank
是不是Symfony的默认错误信息,它是Doctrine默认的注释错误信息@Assert\NotBlank
。当然,您可以为实体上使用的每个字段自定义此错误消息。只需以这种方式在括号中添加您的消息:
/**
* @var \DateTime $startDate
*
* @Assert\NotBlank(message="The start date should not be blank/is mandatory.")
* @ORM\Column(name="startDate", type="date", nullable = false)
*/
private $startDate;
我知道您正在处理其他人的代码,有很多实体和字段,但如果您花时间替换大部分默认消息,现在和以后都可以为您节省很多时间。
对于 Symfony 4.x+(可能适用于较低版本)。
// $form = $this->createForm(SomeType::class);
// $form->submit($data);
// if (!$form->isValid()) {
// var_dump($this->getErrorsFromForm($form));
// }
private function getErrorsFromForm(FormInterface $form, bool $child = false): array
{
$errors = [];
foreach ($form->getErrors() as $error) {
if ($child) {
$errors[] = $error->getMessage();
} else {
$errors[$error->getOrigin()->getName()][] = $error->getMessage();
}
}
foreach ($form->all() as $childForm) {
if ($childForm instanceof FormInterface) {
if ($childErrors = $this->getErrorsFromForm($childForm, true)) {
$errors[$childForm->getName()] = $childErrors;
}
}
}
return $errors;
}