Forms Symfony2表单提交无效的布尔值

Forms 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->

我对Symfony(v2.3.2)表单有一个奇怪的问题。这是一种非常简单的形式,没有关系。我还应该注意到,此表单仅在RESTAPI中使用

所以我有一个已发布的字段(布尔值)。在实体上,默认设置为false

在更新时,REST API客户端发送正确的PUT请求,即aka
..&[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);
    }
}