【问题标题】:Symfony2 invalid form without errorsSymfony2无效形式没有错误
【发布时间】:2012-06-27 20:51:07
【问题描述】:

我遇到了 Symfony2 生成的 CRUD 表单的问题。 (使用 MongoDB Documents,但我认为这无关)

在我的控制器的 createAction() 方法中,当我调试表单结果时:

$form->isValid() // returns false

$form->getErrors() // returns en empty array(0) {}

所以,我在我的树枝模板上使用 form_errors(form) 没有得到任何东西(这似乎很正常,因为 $form->getErrors() 为空返回)

而且写出来的值不会换成表格...

有人有想法吗?

【问题讨论】:

  • 您能否编辑您的问题以包含您的validation.xml 或您的验证注释。

标签: forms validation symfony


【解决方案1】:

您的验证出现问题。表单在提交时未验证。我将假设您正在使用注释进行验证。确保你在实体的顶部有这个。

use Symfony\Component\Validator\Constraints as Assert;

还有这个在每个属性之上

/**      
 * @Assert\NotBlank()      
 */

NotBlank() 可以更改为任何约束以满足您的需求。

有关验证的更多信息,请访问: http://symfony.com/doc/current/book/validation.html

有关断言约束的更多信息,请参见: http://symfony.com/doc/current/book/validation.html#constraints

【讨论】:

  • 我正在使用 MongoDB,所以我没有实体,只有文档。并且在我的文档类文件中已经准备好这一行,否则我会收到另一个 PHP 错误或警告;)我想我的错误来自这个注释,因为我的表单上有文件字段......我稍后再试。谢谢!
【解决方案2】:

首先要了解的是验证是在模型上完成的,而不是在表单上完成的。表单可以包含错误,但前提是它有一个映射到未验证的属性的字段。因此,如果您的表单不包含无效字段(可能是对不在表单中的属性的NotNull 断言),它将不会显示错误。

第二件事是$form->getErrors() 只会显示该级别的错误,每个表单子级都可以包含自己的错误。因此,如果您想检查错误,您应该遍历字段并在每个字段上调用 ​​getErrors。 Form 类上的 getErrors 方法可能具有这种欺骗性。

【讨论】:

  • 我不知道,谢谢,我想我找到了答案。我试试看!
  • 如果您这样做了,请将其标记为已接受的答案,以便其他有此问题的人也可以从中受益。
  • 我遇到了同样的问题,我使用 createForm 并有一个类型添加一个文本字段。为什么它会创建一个子窗体?!我只有一个文本字段...
  • 您还可以通过传递 'true' 作为第一个参数来获取子错误:$form->getErrors(true)
【解决方案3】:

要调试表单,请使用$form->getErrorsAsString() 而不是$form->getErrors()

$form->getErrorsAsString() 只能用于调试表单...它将包含每个子元素的错误,这与$form->getErrors() 不同。

正如彼得所提到的,$form->getErrors() 不会返回子表单的所有错误的总和。

要了解一个表单是如何无效并让 getErrors() 返回一个空数组的,您可以查看 symfony 表单类的 isValid() 方法。如您所见,表单无效的情况有两种,第一种是对通用表单进行测试,第二种情况是对每个子元素进行测试。

public function isValid()
{
    //...

    //CASE I : IF CHILD ELEMENTS HAVE ERRORS, $this->errors WILL CONTAIN
    //THE ERROR ON THE CHILD ELEMENT AND NOT ON THE GENERAL 'errors' FIELD 
    //ITSELF

    if (count($this->errors) > 0) {
        return false;
    }

    //CASE II: AND THIS IS WHY WE ARE TESTING THE CHILD ELEMENTS AS WELL
    //TO CHECK WHETHER THERE ARE VALID OR NOT

    if (!$this->isDisabled()) {
        foreach ($this->children as $child) {
            if (!$child->isValid()) {
                return false;
            }
        }
    }

    return true;
}

因此每个子表单都可以包含一个错误,但$form->getErrors() 本身不会返回所有错误。考虑到一个包含许多子元素的表单,如果 CSRF 不正确,您通常会遇到带有 CSRF 错误的 $form->getErrors()。

【讨论】:

  • 非常感谢这个答案。如果没有它,我将不得不花费大量时间来调试无效字段。
  • $form->getErrorsAsString() 在 Symfony 2.5+ 中被弃用
  • 非常好的点@ChristoKiwi!如果您愿意,请随时更新答案!
  • 对于弃用警告,请改用getErrors(),他们还说要转换为字符串,我结束了使用(string)$form->getErrors(true);
  • 对于 Symfony 3.2,将错误作为字符串获取,如下所示:$form->getErrors(true, false);
【解决方案4】:

对我来说,表单没有提交,即使我有一个提交按钮。 我添加了解决问题的代码

$request = $this->get('request');
if($request->isMethod("POST")){
      $form->submit($request);
        if($form->isValid()){
        // now true
        }
}

【讨论】:

  • 看起来很奇怪,同一个页面不是有好几个表格吗?
  • 也许你错过了 $form->handleRequest($this->getRequest()); 指令。它应该在 isValid() 检查之前调用。
【解决方案5】:

我也遇到了同样的问题。对我来说,该表单无效,但使用 $form->getErrors()$form->getErrorsAsString() 无法得到任何错误。后来我发现我忘记将 CSRF 令牌传递给表单,所以它不会被提交,并且$form->handleRequest($request) 什么也没做(没有验证)。当我看到@pit的答案时,我尝试使用

$form->submit($request);

$form->getErrorsAsString();

它返回了一个错误:

错误:CSRF 令牌无效。请尝试重新提交表单。

以下是 Symfony2 文档中的一些解释:http://symfony.com/doc/current/book/forms.html#handling-form-submissions

【讨论】:

    【解决方案6】:

    Symfony 2.6 更新

    所以取决于你的 Symfony2 版本:

    die($form->getErrorsAsString());
    

    截至getErrorsAsString() 函数已被弃用(将在 Symfony3 中删除),您应该使用以下方法:

    die((string) $form->getErrors());     // Main errors
    die((string) $form->getErrors(true)); // Main and child errors
    

    开始,如果你激活了DebugBundle,也可以使用dump(开发环境)功能:

    dump((string) $form->getErrors());     // Main errors
    dump((string) $form->getErrors(true)); // Main and child errors
    

    【讨论】:

    • 谢谢,没注意到!
    • 这个帮助我解决了我的问题,谢谢! (使用 Symfony 2.8)
    • $form->getErrors(true) 不错!
    • $form->getErrors(true) 在 symfony 3.4 上也是如此。不知道“深度”参数,它显示来自孩子的错误。
    【解决方案7】:

    如果您通过 AJAX 发送数据,您可能没有在数据键中包含表单名称,因此是……的“受害者”

    # line 100 of Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationRequestHandler.php 
    // Don't submit the form if it is not present in the request
    

    这意味着,在尝试处理请求时,请求处理机制在 GET/POST 数据中找不到您的表单名称(即数组)。

    当您以通常的方式呈现表单时,其每个字段都包含您的表单名称作为其名称属性 my_form[child_field_name] 的前缀。

    使用 ajax 时,请将表单名称作为前缀添加到数据中!

    data : {
        "my_form" : {
           "field_one" : "field_one_value"
           ...
        }
    }
    

    【讨论】:

      【解决方案8】:

      是的 这是正确的,它说的是 Peter Kruithof 在 SF 2.8 中,这是我的功能,用于获取字段的错误

       private function getErrorsForm(\Symfony\Component\Form\Form $form)
      {
          $response =  array();
      
          foreach ($form as $child) {
               foreach ($child->getErrors(true) as $error) {
                  $response[$child->getName()][] = $error->getMessage();
               }
          }
      
          return $response;
      }
      

      【讨论】:

      • 或者:$form->getErrors(true)
      【解决方案9】:

      我遇到了这个错误,发现我忘记“处理”请求。确保你有那个...

      public function editAction(Request $request)
      {
          $form = $this->createForm(new CustomType(),$dataObject);
          /**  This next line is the one I'm talking about... */
          $form->handleRequest($request);
          if ($request->getMethod() == "POST") {
              if ($form->isValid()) {
              ...
      

      【讨论】:

        【解决方案10】:

        根据文档,从 Symfony 3 开始,您应该使用新的实现:

        $errors = (string) $form->getErrors(true, false);

        这会将所有错误作为一个字符串返回。

        【讨论】:

          【解决方案11】:

          对于 Symfony (>= 3.2 - 4),您可以使用:

          foreach($form->getErrors(true, false) as $er) {
              print_r($er->__toString());
          }
          

          清楚地看到错误。

          【讨论】:

          • 我认为直接使用“魔术”__toString() 方法不是一个好习惯。正如亚当已经建议的那样,更容易将对象直接转换为字符串。
          • 当然可以,但是,如果您想在没有太多编码的情况下查看问题所在,它会有所帮助。
          猜你喜欢
          • 2016-04-25
          • 2013-10-14
          • 1970-01-01
          • 2017-07-07
          • 2019-07-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多