sourcecode

json 인코딩된 폼 오류를 심포니로 반환하는 방법

copyscript 2023. 7. 28. 22:32
반응형

json 인코딩된 폼 오류를 심포니로 반환하는 방법

양식을 제출하는 웹 서비스를 만들고 싶고, 오류가 발생하면 어떤 필드가 잘못되었는지 알려주는 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"
    }
}

어떻게 하면 그것을 달성할 수 있을까요?

저는 이것을 사용하고 있습니다. 이것은 꽤 잘 작동합니다.

/**
 * 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;
}

저는 마침내 이 문제에 대한 해결책을 여기서 찾았습니다. 최신 기호 변경 사항을 준수하기 위해 작은 수정만 필요했고 매력적으로 작동했습니다.

수정은 33번 라인을 교체하는 것으로 구성됩니다.

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

와 함께

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

왜냐하면 Form\Button의 동의어로 도입되면 항상 Form\Form의 인스턴스가 예상되는 직렬화 함수에서 유형 불일치가 발생하기 때문입니다.

서비스로 등록할 수 있습니다.

services:
form_serializer:
    class:        Wooshii\SiteBundle\FormErrorsSerializer

그런 다음 저자가 제안하는 대로 사용합니다.

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

이것은 나에게 효과가 있습니다.

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

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();
}

(getId() 메서드가 $error 개체에 존재한다고 가정)

다른 사람들의 답변을 읽음으로써 저는 그것을 제 필요에 맞게 개선할 수 있었습니다.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;
    }
}

이 정도면 효과가 있을 겁니다.이 정적 메서드는 다음을 통해 재귀적으로 실행됩니다.Symfony\Component\Form\FormErrorIterator전화로 배달된$form->getErrors(true, false).

<?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."
        }
    }
}

언급URL : https://stackoverflow.com/questions/24556121/how-to-return-json-encoded-form-errors-in-symfony

반응형