Как мне получить доступ к изначально отправленным данным формы Symfony?

Я работаю с некоторыми формами Symfony, и мне нужно получить доступ к изначально отправленным (нетронутым) данным. Все методы доступа к данным $form->getData(), $form->getViewData() и $form->getModelData() дают мне уже преобразованные значения, но мне нужны данные, как в событии PRE_SUBMIT.

Я мог бы написать слушателя и извлечь их на PRE_SUBMIT, но тогда мне придется хранить эту информацию где угодно и обращаться к ней в моем сервисе, работая с формой. На данный момент моя служба видит только переданный объект формы и выполняет свою работу без каких-либо других зависимостей.

Другие обходные пути включают чтение из объекта запроса. Не выглядит разумным вариантом, потому что форма может быть заполнена из других источников (например, сеанс, это форма фильтра).

Есть ли «официальный» способ доступа к изначально отправленным данным непосредственно из объекта формы? Если нет, стоит ли запрашивать функцию? Есть какие-нибудь мнения по этому поводу?

(Мой вариант использования - это форма фильтра, где состояние сохраняется и извлекается из сеанса. Поскольку форма может быть отправлена ​​без данных, поступающих из запроса, включающего режимы для HTML-POST, HTML-GET и JSON-POST, я не не хочу просто хранить данные запроса.)

Изменить 2018-06-07: в соответствии с просьбой в комментариях я привожу пример кода:

/**
 * handles the filterForm request reading POST-data or namespaced JSON payload with POST method or any standard form request
 *
 * @param FormInterface $filterForm
 * @return void
 * @throws ResponseException
 */
public function handleRequest(FormInterface $filterForm): void
{
    // reset the filter state in the session, if a reset_filter query parameter was set
    if (true === $this->request->query->getBoolean('reset_filter', false)) {
        $this->setFilterState(null, $this->request->attributes->get('_route'));
        $this->filterIsActive = true;
    }

    // handle filter submission in json context
    if ($this->request->isMethod('POST') && $this->request->attributes->get('_format') === 'json') {
        if ($this->request->get($filterForm->getName())) {
            $submitData = $this->request->get($filterForm->getName());
        }
        else {
            $postData = JsonHelper::parseAndCheckJsonPostData($this->request);
            if ($postData instanceof Response) {
                throw new ResponseException($postData);
            }
            $submitData = $postData[$filterForm->getName()] ?? null;
        }
        if (null !== $submitData) {
            dump($submitData);
            $filterForm->submit($submitData, true);
            dump($filterForm->getData());
        }
    }
    else {
        // @todo find a smooth way to get the original submitted data of a form, when it is handled by the default handleRequest()-menthod
        $submitData = null;
        $filterForm->handleRequest($this->request);
    }

    // load the filter state from the session and submit it, if it is not yet set and we are in HTML context
    if (!$filterForm->isSubmitted()
        && $this->request->attributes->get('_format') === 'html'
        && null !== $this->getFilterState($this->request->attributes->get('_route'))
    ) {
        $filterForm->submit($this->getFilterState($this->request->attributes->get('_route')));
    }

    if ($filterForm->isSubmitted()) {
        $this->filterIsActive = true;

        // return an JSON error-document, if the filter form is not valid
        if (!$filterForm->isValid() && $this->request->attributes->get('_format') === 'json') {
            throw new ResponseException(
                new JsonResponse([
                    'type' => 'error',
                    'message' => $this->translator->trans('Form.Filter.errorMessage'),
                    'filterForm' => $this->serializer->normalize($filterForm->createView()),
                ], Response::HTTP_BAD_REQUEST)
            );
        }

        // store the new filter state, if filter is active and and valid
        if ($filterForm->isValid() && null !== $submitData) {
            $this->setFilterState($submitData, $this->request->attributes->get('_route'));
        }
    }
}

Выводит это:

array:4 [▼
    "singleEntity" => "1"
    "multipleEntities" => array:1 [▼
        0 => "1"
    ]
    "dateRange" => array:2 [▼
        "left_date" => "06.06.2018"
        "right_date" => "07.06.2018"
    ]
    "submit" => true
]

array:11 [▼
    "singleEntity" => MySingleEntity {#3739 ▶}
    "facilities" => ArrayCollection {#3419 ▼
        -elements: array:1 [▼
            0 => MyMultiEntity {#3799 ▶}
        ]
    }
    "createdOrUpdatedBetween" => array:2 [▼
        "left_date" => DateTime @1528236000 {#3408 ▼
            date: 2018-06-06 00:00:00.0 Europe/Berlin (+02:00)
        }
        "right_date" => DateTime @1528322400 {#3397 ▼
            date: 2018-06-07 00:00:00.0 Europe/Berlin (+02:00)
        }
    ]
]

Если это форма фильтра, зачем вам преобразовывать значения? Не могли бы вы объяснить случай поподробнее? Обычно в форме фильтра значения не преобразуются.

gvf 05.06.2018 23:26

Формы используют LexikFormFilterBundle, где как минимум поля Date и DateTime преобразуются в DateTime-объекты. В моем случае я часто использую Entity-фильтры, и их представленные значения преобразуются в их сущности. Это здорово, так как это очень помогает в обработке логики фильтра.

spackmat 06.06.2018 09:16

Можете ли вы предоставить пример использования данных, которые поступают из запроса (и вам нужны в необработанном формате), и во что они преобразуются? Кроме того, для чего вам нужны необработанные данные? (Просто спросите, может быть, есть лучший подход, чем пытаться получить необработанные данные из формы)

gvf 06.06.2018 23:41

Я не хотел обсуждать свою реализацию, но теперь вы спросили, я предоставил свой код. Как видите, я сохраняю отправленные данные в сеансе и загружаю (и отправляю) их снова, когда пользователь в следующий раз загрузит html-версию страницы. Поэтому, когда пользователи возвращаются, у них есть последнее состояние фильтра. На данный момент рассматриваемый случай не реализуется на практике (фильтры применяются только через POST / JSON), но, возможно, это вызовет проблему в будущем. Итак, я ищу окончательное решение без взлома.

spackmat 07.06.2018 09:47
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Symfony Station Communiqué - 17 февраля 2023 г
Symfony Station Communiqué - 17 февраля 2023 г
Это коммюнике первоначально появилось на Symfony Station , вашем источнике передовых новостей Symfony, PHP и кибербезопасности.
Управление ответами api для исключений на Symfony с помощью KernelEvents
Управление ответами api для исключений на Symfony с помощью KernelEvents
Много раз при создании api нам нужно возвращать клиентам разные ответы в зависимости от возникшего исключения.
0
4
543
1

Ответы 1

У меня есть два варианта сохранения отправленных данных

1) Возьмите прямо из запроса

$submitted_data = [];
foreach ($form->all() as $child) {
    if ($request->request->has($child->getName())) {
        $submitted_data[$child->getName()] = $request->request->get($child->getName());
    }
}

2) используйте события формы

$submitted_data = null;
$formBuilder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) use (&$submitted_data) {
    $submitted_data = $event->getData();
});

Оба варианта и почему они не являются хорошими вариантами обсуждаются внутри вопроса. В основном вопрос заключается в получении необработанных данных из объекта формы, который передается методу handleRequest, который не должен иметь никаких других зависимостей. Я мог бы сделать PRE_SUBMIT-материал и сохранить необработанные данные для запроса, если они не исходят оттуда. Таким образом, метод handleRequest всегда получает необработанные данные формы из запроса, даже если форма была заполнена из пользовательского сеанса. Немного хакерский, но может быть решением.

spackmat 28.03.2020 23:32

Другие вопросы по теме