Forms Symfony2表单提交无效的布尔值
我对Symfony(v2.3.2)表单有一个奇怪的问题。这是一种非常简单的形式,没有关系。我还应该注意到,此表单仅在RESTAPI中使用 所以我有一个已发布的字段(布尔值)。在实体上,默认设置为false 在更新时,REST API客户端发送正确的PUT请求,即akaForms Symfony2表单提交无效的布尔值,forms,rest,symfony,checkbox,boolean,Forms,Rest,Symfony,Checkbox,Boolean,我对Symfony(v2.3.2)表单有一个奇怪的问题。这是一种非常简单的形式,没有关系。我还应该注意到,此表单仅在RESTAPI中使用 所以我有一个已发布的字段(布尔值)。在实体上,默认设置为false 在更新时,REST API客户端发送正确的PUT请求,即aka..&[entity]published=0&..。此值也显示在Symfony profiler的表单参数中 然而,我注意到数据库中的实际值被设置为true(或1,因为它是tinyint) 所以,为了找出问题所在,我在$form->
..&[entity]published=0&..
。此值也显示在Symfony profiler的表单参数中
然而,我注意到数据库中的实际值被设置为true(或1,因为它是tinyint)
所以,为了找出问题所在,我在$form->submit($request)之后添加了throw语句代码>
throw new\Exception(sprintf('Request:%s,form:%s',$Request->get('entity')['published'],$form->get('published')->getData())代码>
或
throw new\Exception(sprintf('Request:%s,form:%s',$Request->get('entity')['published'],$form->getData()->getPublished())代码>
异常消息显示:请求:0,表单:1
。这意味着在submit方法中的某个地方,字符串值“0”被转换为1
该字段由$builder->add('published','checkbox',['required'=>false])构造而成。
我也注意到了一些奇怪的事情,这可能是相关的。在Symfony profiler的面板请求中,我得到了错误:警告:json_encode():classes.php行3758中的UTF-8序列无效
,我没有发送任何奇怪的字符-只发送单词“test”。进一步的调查显示,典型的HTML表单复选框只有在选中时才会发送到服务器。所以我假设发送设置为0 | false | off的值将使其工作,就好像它将设置为true一样
因此,如果您将表单小部件设置为键入checkbox,则如果希望将其设置为false,则不要在请求中发送checkbox。在我的例子中,它看起来是这样的:
Array
(
[entity] => Array
(
[id] => 73
[_token] => d63dad39ea458f7d3c7ae5dbea10c325cb9ee93d
)
)
否则发送任何内容,0、false、off也将起作用
Array
(
[entity] => Array
(
[id] => 73
[published] => 1|0|false|on|off
[_token] => d63dad39ea458f7d3c7ae5dbea10c325cb9ee93d
)
)
当使用PUT时,这碰巧有点问题。。。
我通过在解决此问题的所有表单中添加一个订阅者来解决此问题(此代码还解决了在不填写所有数据的情况下使用PUT的问题):
您不应该在API中使用复选框表单类型,0并不意味着false
您应该实现一个新的boolean表单类型,它将1、'1'和true转换为true,将其他所有内容转换为false(例如)
以下是一个例子:
class RestFormSubscriber implements EventSubscriberInterface {
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents()
{
return array(FormEvents::PRE_SUBMIT => "preSubmit");
}
/**
* Remove null fields on update
* Fixes boolean value
* @param FormEvent $event
*/
public function preSubmit(FormEvent $event)
{
$form = $event->getForm();
$data = $event->getData();
$isPUT = strtoupper($form->getConfig()->getMethod()) == "PUT";
$accessor = PropertyAccess::createPropertyAccessor();
foreach ($form->all() as $name => $child) {
if ($isPUT && !isset($data[$name])) {
$form->remove($name);
continue;
}
if(is_bool($accessor->getValue($form->getData(), $name))) {
$val = $data[$name];
$data[$name] = ($val=="true")||($val=="1")||($val=="on");
}
}
$event->setData($data);
}
}