Symfony2无效形式没有错误

Posted

技术标签:

【中文标题】Symfony2无效形式没有错误【英文标题】:Symfony2 invalid form without errors 【发布时间】: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 或您的验证注释。 【参考方案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 版本:

symfony2.3

die($form->getErrorsAsString());

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

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

从symfony2.6开始,如果你激活了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() 方法不是一个好习惯。正如亚当已经建议的那样,更容易将对象直接转换为字符串。 当然可以,但是,如果您想在没有太多编码的情况下查看问题所在,它会有所帮助。

以上是关于Symfony2无效形式没有错误的主要内容,如果未能解决你的问题,请参考以下文章

symfony2 CSRF 无效

Symfony2:记住我身份验证时无效的 CSRF 令牌

如何正确地使 Symfony2 应用程序的生产缓存无效?

学说 symfony2 错误:Cocina\ComprasBundle\Entity\Productos 类没有名为proveedores 的关联

Symfony2 禁用选择

Symfony2 - 数组到字符串转换错误