3

我对 Symfony (v 2.3.2) 表单有一个奇怪的问题。这是没有关系的非常简单的形式。我还应该指出,这种形式仅用于 REST API。

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

更新时,REST API 客户端发送正确的 PUT 请求...&[entity]published=0&...。这个值也显示在 Symfony 分析器的表单参数中。

但是我注意到数据库中的实际值设置为 true(或 1,因为它是 tinyint)。

所以,为了找出问题所在,我在后面添加了 throw 语句$form->submit($request);

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()));

异常消息说:Request: 0, form: 1。这意味着在提交方法中的某处,字符串值“0”被转换为 1。

该字段由$builder->add('published', 'checkbox', [ 'required' => false ])

我也注意到奇怪的事情,这可能是相关的。在 Symfony 分析器的面板请求中,我收到错误:Warning: json_encode(): Invalid UTF-8 sequence in classes.php line 3758,我没有发送任何奇怪的字符 - 只是单词“test”。

4

3 回答 3

5

您不应该在 API 中使用复选框表单类型,0 并不意味着错误。

您应该实现一个新的布尔表单类型,它将 1、'1' 和 true 转换为 true,并将其他所有内容转换为 false(例如)。

这是一个例子:https ://gist.github.com/fsevestre/abfefe0b66e5f5b24c60

于 2015-11-29T17:02:54.477 回答
2

进一步调查显示,典型的 HTML 表单复选框仅在选中时才会发送到服务器。所以我假设发送值设置为 0|false|off 会使它像设置为 true 一样工作。

因此,如果您将表单小部件设置为类型复选框,如果您希望将其设置为 false,请不要在请求中发送复选框。就我而言,它看起来像这样:

Array
(
    [entity] => Array
    (
        [id] => 73
        [_token] => d63dad39ea458f7d3c7ae5dbea10c325cb9ee93d
    )
)

否则发送任何东西,0,false,off 也可以

Array
(
    [entity] => Array
    (
        [id] => 73
        [published] => 1|0|false|on|off
        [_token] => d63dad39ea458f7d3c7ae5dbea10c325cb9ee93d
    )
)
于 2013-08-07T12:17:32.077 回答
0

当使用 PUT 时,这碰巧有点问题......我通过向我所有解决此问题的表单添加订阅者来解决它(此代码还解决了使用 PUT 而不填充所有数据的问题):

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);
    }
}
于 2015-07-16T09:12:57.353 回答