【问题标题】:Symfony form: how to know precisely which field cause an errorSymfony 表单:如何准确知道哪个字段导致错误
【发布时间】:2016-12-05 14:34:37
【问题描述】:

我必须解决一个 Symfony 表单验证的问题,它由 30 个子表单组成,每个子表单由 3 个实体组成,每个实体大约有 20-25 个字段。所以这个单一的表单包含超过 1800 个字段:-(.

在验证时,编写这个丑陋表单的开发人员在一行中检查它,如下所示:

if ($form->isValid()) {
    [...]
}

如果表格无效,在树枝模板中,他只写:

{{ form_errors(form) }}

因此,如果我使用当前值加载表单,并在不进行任何修改的情况下提交它,验证失败并重复两次相同的 Symfony 默认消息:

此值不应为空。

此值不应为空。

但我不知道 1800 多个字段中的哪一个会导致错误,而且我没有找到如何向 Symfony 询问给定错误,这是导致错误的字段。

我如何知道是哪个字段导致了错误?


编辑:我听从了 Alexander 的建议,并且:

$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
}

不知道发生在哪里。

【问题讨论】:

  • 对不起。我已经编辑了我的答案。您需要像在 getErrors() 中那样处理表单本身。

标签: php forms symfony validation symfony-forms


【解决方案1】:

我不会完全回答你的问题,即使我了解你想要什么以及你想做什么,我也会建议你另一种(也许更好)的方式。

您的错误消息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;

我知道您正在编写其他人的代码,有很多实体和字段,但如果您花时间替换大部分默认消息,现在和以后可以为您节省大量时间。

【讨论】:

  • 我在代码中发现了大约 180 个注释“NotBlank”,没有错误消息...最后,我按照您建议的实体和字段名称为每个消息添加了一条消息,然后 Bam !错误现在很清楚 (Penalty: the "Taxes" field is mandatory.)。你拯救了我的一周!
【解决方案2】:

我很久以前在网上的某个地方找到了这个方法,我每天都在使用它:)

/**
 * @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

【讨论】:

  • 我尝试了你的建议。和以前一样,我给了我一个包含错误消息的数组,但它没有给我 which 字段导致错误...
【解决方案3】:

上做一个 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
        }

【讨论】:

  • 循环中的 $child->getName() 是什么?
  • 如果你有一个空数组,那么循环没有继续,所以你找到了无效的孩子。尝试用 $child->getName() 找出他的名字
【解决方案4】:

您可以使用 XDEBUG 并查看 $failed 变量中的错误。

【讨论】:

    【解决方案5】:

    适用于 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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-09-29
      • 1970-01-01
      • 2013-05-19
      • 1970-01-01
      • 1970-01-01
      • 2020-09-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多