【发布时间】:2016-01-05 18:42:31
【问题描述】:
我很难弄清楚如何使用 Symfony 表单处理 JSON 请求(使用 v3.0.1)。
这是我的控制器:
/**
* @Route("/tablet")
* @Method("POST")
*/
public function tabletAction(Request $request)
{
$tablet = new Tablet();
$form = $this->createForm(ApiTabletType::class, $tablet);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($tablet);
$em->flush();
}
return new Response('');
}
还有我的表格:
class ApiTabletType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('macAddress')
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => 'AppBundle\Entity\Tablet'
]);
}
}
当我发送一个将 Content-Type 标头正确设置为 application/json 的 POST 请求时,我的表单无效...所有字段均为空。
以下是我在评论if ($form->isValid()) 行时收到的异常消息:
执行“INSERT INTO tablet”时发生异常 (mac_address, site_id) VALUES (?, ?)' with params [null, null]:
我尝试过每次发送不同的 JSON 结果相同:
{"id":"9","macAddress":"5E:FF:56:A2:AF:15"}{"api_tablet":{"id":"9","macAddress":"5E:FF:56:A2:AF:15"}}
"api_tablet" 是 getBlockPrefix 返回的内容(Symfony 3 等价于 Symfony 2 中的表单类型 getName 方法)。
谁能告诉我我做错了什么?
更新:
我尝试在我的表单类型中覆盖 getBlockPrefix。表单字段不再有前缀,但仍然没有运气:/
public function getBlockPrefix()
{
return '';
}
【问题讨论】:
-
渲染表单并查看元素名称。您会很快看到 macAddress 元素被命名为“form[macAddress]”之类的东西,我自己不使用表单来处理其他内容。我认为命名问题比它的价值更麻烦。但其他人却不这么认为。可能想看看 FOSRestBundle。
-
我尝试渲染表单,表单名为“api_tablet”,元素为“api_tablet_macAddress”。我尝试使用“api_tablet_macAddress”而不是“macAddress”(有或没有父节点,正如我的问题中提到的那样),但也没有成功。 (我想避免使用 FOSRestBundle,因为我需要的 API 非常小。我宁愿不为这样的基本任务添加包。)
-
您正在查看 id。元素名称为:name="api_tablet[macAddress]"。将 blockName 设置为 '' 确实会使 api_table 前缀消失,尽管您的表单名称现在也是空白的,这并不是真正可取的。顺便说一句,javascript 有时会遇到 [] 问题,因此请使用浏览器 F12 键来验证实际发布的内容。
-
你说得对,我的错。我删除了 getBlockPrefix 覆盖并尝试在我的 JSON 中使用括号,但也没有运气。
-
问题是 JSON 请求(请求主体是 JSON 字符串的请求)的填充方式与“常规”HTTP 请求不同(您可以将
Request对象转储到看到不同)。因此,您需要首先“解码”请求正文。您可以查看the BodyListener from FOSRestBundle 以获得一些灵感(实现自定义请求处理程序可能也可以,但恕我直言,这并不容易)。