【问题标题】:how to return json encoded form errors in symfony如何在 symfony 中返回 json 编码格式错误
【发布时间】:2014-08-24 17:17:05
【问题描述】:

我想创建一个向其提交表单的 Web 服务,如果出现错误,则返回一个 JSON 编码列表,告诉我哪个字段是错误的。

目前我只得到错误消息列表,但没有 html id 或有错误的字段名称

这是我当前的代码

public function saveAction(Request $request)
{
    $em = $this->getDoctrine()->getManager();

    $form = $this->createForm(new TaskType(), new Task());

    $form->handleRequest($request);

    $task = $form->getData();

    if ($form->isValid()) {

        $em->persist($task);
        $em->flush();

        $array = array( 'status' => 201, 'msg' => 'Task Created'); 

    } else {

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

        $errorCollection = array();
        foreach($errors as $error){
               $errorCollection[] = $error->getMessage();
        }

        $array = array( 'status' => 400, 'errorMsg' => 'Bad Request', 'errorReport' => $errorCollection); // data to return via JSON
    }

    $response = new Response( json_encode( $array ) );
    $response->headers->set( 'Content-Type', 'application/json' );

    return $response;
}

这会给我一个类似的回应

{
"status":400,
"errorMsg":"Bad Request",
"errorReport":{
        "Task cannot be blank",
        "Task date needs to be within the month"
    }
}

但我真正想要的是类似的东西

{
"status":400,
"errorMsg":"Bad Request",
"errorReport":{
        "taskfield" : "Task cannot be blank",
        "taskdatefield" : "Task date needs to be within the month"
    }
}

我怎样才能做到这一点?

【问题讨论】:

    标签: php ajax json forms symfony


    【解决方案1】:

    我正在使用它,它运行良好:

    /**
     * List all errors of a given bound form.
     *
     * @param Form $form
     *
     * @return array
     */
    protected function getFormErrors(Form $form)
    {
        $errors = array();
    
        // Global
        foreach ($form->getErrors() as $error) {
            $errors[$form->getName()][] = $error->getMessage();
        }
    
        // Fields
        foreach ($form as $child /** @var Form $child */) {
            if (!$child->isValid()) {
                foreach ($child->getErrors() as $error) {
                    $errors[$child->getName()][] = $error->getMessage();
                }
            }
        }
    
        return $errors;
    }
    

    【讨论】:

    • 不幸的是,这对我不起作用,至少不是我想要的方式。非常感谢您的回答
    • 如果它不是一个简单的表单结构并且它没有返回输入字段 ids/names,它就不会正确地遍历表单结构。也许我对问题的解释不够清楚。试试我找到的解决方案,你就会明白了。
    • 是的,它只适用于一级表单。
    • 完美解决方案:)
    【解决方案2】:

    我终于找到了这个问题的解决方案here,它只需要一个小修复来符合最新的 symfony 更改,它就像一个魅力:

    修复包括替换第 33 行

    if (count($child->getIterator()) > 0) {
    

    if (count($child->getIterator()) > 0 && ($child instanceof \Symfony\Component\Form\Form)) {
    

    因为在 symfony 中引入 Form\Button 时,序列化函数会出现类型不匹配,该函数总是期望 Form\Form 的实例。

    您可以将其注册为服务:

    services:
    form_serializer:
        class:        Wooshii\SiteBundle\FormErrorsSerializer
    

    然后按照作者的建议使用它:

    $errors = $this->get('form_serializer')->serializeFormErrors($form, true, true);
    

    【讨论】:

      【解决方案3】:

      这对我有用

       $errors = [];
       foreach ($form->getErrors(true, true) as $formError) {
          $errors[] = $formError->getMessage();
       }
      

      【讨论】:

        【解决方案4】:

        PHP 有关联数组,而 JS 有两种不同的数据结构:对象和数组。

        你要获取的 JSON 是不合法的,应该是:

        {
        "status":400,
        "errorMsg":"Bad Request",
        "errorReport": {
                "taskfield" : "Task cannot be blank",
                "taskdatefield" : "Task date needs to be within the month"
            }
        }
        

        所以你可能想做这样的事情来建立你的收藏:

        $errorCollection = array();
        foreach($errors as $error){
             $errorCollection[$error->getId()] = $error->getMessage();
        }
        

        (假设 $error 对象上存在 getId() 方法)

        【讨论】:

        • 对于字段的 id 或名称,我的意思是我可以用它来定位表单中的字段...例如 html id 或字段名称。
        • 如果您使用 foreach($errors as $key => $error) 进行迭代,您要查找的不是 $key 吗?
        • 不,它只是一个数字索引...我需要一些东西来定位 html 元素
        • @SimonQuest 这个answer(及后续)可能会对您有所帮助。
        【解决方案5】:

        通过阅读其他人的答案,我最终根据自己的需要对其进行了改进。我在 Symfony 3.4 中使用它。

        在这样的控制器中使用:

        $formErrors = FormUtils::getErrorMessages($form);
        
        return new JsonResponse([
            'formErrors' => $formErrors,
        ]);
        

        在单独的 Utils 类中使用此代码

        <?php
        
        namespace MyBundle\Utils;
        
        use Symfony\Component\Form\FormError;
        use Symfony\Component\Form\FormInterface;
        
        class FormUtils
        {
            /**
             * @param FormInterface $form
             * @return array
             */
            public static function getErrorMessages(FormInterface $form)
            {
                $formName = $form->getName();
                $errors = [];
        
                /** @var FormError $formError */
                foreach ($form->getErrors(true, true) as $formError) {
                    $name = '';
                    $thisField = $formError->getOrigin()->getName();
                    $origin = $formError->getOrigin();
                    while ($origin = $origin->getParent()) {
                        if ($formName !== $origin->getName()) {
                            $name = $origin->getName() . '_' . $name;
                        }
                    }
                    $fieldName = $formName . '_' . $name . $thisField;
                    /**
                     * One field can have multiple errors
                     */
                    if (!in_array($fieldName, $errors)) {
                        $errors[$fieldName] = [];
                    }
                    $errors[$fieldName][] = $formError->getMessage();
                }
        
                return $errors;
            }
        }
        

        【讨论】:

          【解决方案6】:

          这样就可以了。此静态方法通过调用$form-&gt;getErrors(true, false) 传递的Symfony\Component\Form\FormErrorIterator 递归运行。

          <?php
          
          
          namespace App\Utils;
          
          
          use Symfony\Component\Form\FormInterface;
          use Symfony\Component\Form\FormError;
          use Symfony\Component\Form\FormErrorIterator;
          
          class FormUtils
          {
              public static function generateErrorsArrayFromForm(FormInterface $form)
              {
                  $result = [];
                  foreach ($form->getErrors(true, false) as $formError) {
                      if ($formError instanceof FormError) {
                          $result[$formError->getOrigin()->getName()] = $formError->getMessage();
                      } elseif ($formError instanceof FormErrorIterator) {
                          $result[$formError->getForm()->getName()] = self::generateErrorsArrayFromForm($formError->getForm());
                      }
                  }
                  return $result;
              }
          }
          

          结果如下:

          {
              "houseworkSection": "All the data of the housework section must be set since the section has been requested.",
              "foodSection": {
                  "requested": {
                      "requested": "This value is not valid."
                  }
              }
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-08-15
            • 2016-10-02
            • 1970-01-01
            • 1970-01-01
            • 2014-04-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多