如何访问Symfony表单最初提交的数据?
我正在使用一些Symfony表单,需要访问最初提交的(未触及的)数据。数据访问器方法如何访问Symfony表单最初提交的数据?,symfony,symfony-forms,Symfony,Symfony Forms,我正在使用一些Symfony表单,需要访问最初提交的(未触及的)数据。数据访问器方法$form->getData(),$form->getViewData()和$form->getModelData()都为我提供了已转换的值,但我需要的数据与PRE_SUBMIT事件一样 我可以编写一个侦听器,并在提交前提取这些信息,但随后我必须将这些信息存储在任何地方,并在使用表单的服务中访问这些信息。目前,我的服务只看到传递的表单对象,并且在没有其他依赖项的情况下工作 其他解决方法包括读取请求对象。看起来不是
$form->getData()
,$form->getViewData()
和$form->getModelData()
都为我提供了已转换的值,但我需要的数据与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)
}
]
]
我有两个选择如何保存提交的数据 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();
});
如果它是一个过滤表单,为什么需要转换值?你能详细解释一下这个案子吗?通常,在筛选表单中,不会转换值。表单使用LexikFormFilterBundle,其中至少将日期和日期时间字段转换为日期时间对象。在我的例子中,我经常使用实体过滤器,它们提交的值被转换成它们的实体。这很好,因为这有助于处理过滤逻辑。您能为来自请求的数据(您需要原始格式)提供一个用例吗?它转换成什么?另外,您需要原始数据做什么?(只是问一个可能有更好的方法,而不是试图从表单中获取原始数据)我不想讨论我的实现,但现在你问了,我提供了我的代码。如您所见,我将提交的数据存储在会话中,并在用户下次加载页面的html版本时再次加载(并提交)它。因此,当用户返回时,他们就有了最后一个过滤器状态。目前,这种情况在实践中并未发生(过滤器仅通过POST/JSON应用),但这可能会在将来引发问题。因此,我正在寻找一个最终的非黑客解决方案。这两个选项以及为什么它们不是好的选项都在问题中讨论。问题基本上是从传递给handleRequest方法的表单对象获取原始数据,该方法不应具有任何其他依赖项。我可以做PRE_SUBMIT-stuff并将原始数据存储到请求中,如果它不是来自那里的话。因此handleRequest方法总是从请求中获取原始表单数据,即使表单是从用户会话中填充的。有点不对劲,但可能是一个解决方案。