Symfony2 动态表单修改 ajax jquery 无效的 CSRF 令牌


symfony2 dynamic form modification ajax jquery invalid CSRF token

假设我有产品,产品可以promo。单击复选框促销时promoPrice我希望显示该字段。这是我AbstractType的一个例子

//...
//$builder->add(..);
$builder->add('promoProduct', 'checkbox', [
    'required' => false,
]);
$builder->add('promoPrice', 'hidden')
//$builder->add(..);
$formModifier = function (FormInterface $form, $promoProduct = null) {
    if ($promoProduct) {
        $form->add('promoPrice', 'money');
    }
};
$builder->addEventListener(
    FormEvents::PRE_SET_DATA,
    function (FormEvent $event) use ($formModifier) {
        $data = $event->getData();
        $formModifier($event->getForm(), $data->getPromoProduct());
    }
);
$builder->get('promoProduct')->addEventListener(
    FormEvents::POST_SUBMIT,
    function (FormEvent $event) use ($formModifier) {
        $promoProduct = $event->getForm()->getData();
        $formModifier($event->getForm()->getParent(), $promoProduct);
    }
);
//...

这是我的 JavaScript

    ...
    var $promoProduct = $('#product_form_promoProduct');
    $promoProduct.change(function() {
        var $form = $(this).closest('form');
        var data = {};
        if ($promoProduct.is(':checked')) {
            data[$promoProduct.attr('name')] = 1;
        } else {
            data[$promoProduct.attr('name')] = 0;
        }
        $.ajax({
            url: $form.attr('action'),
            type: $form.attr('method'),
            data: data,
            success: function(html) {
                $('#product_form_promoPrice').replaceWith(
                    $(html).find('#product_form_promoPrice')
                );
            }
        });
    });
    ...

所以这是我的问题,当我提交带有数据的表单时product_form[promoProduct]:0响应附带promoProduct选中字段promoPrice并且由于正在检查promoProduct字段而可见字段。同样在响应中,我收到"无效的 CSRF 令牌错误"。似乎我通过 AJAX 发送的数据没有在表单中使用,也许是因为无效的 csrf 令牌?

我正在逐步遵循本指南 http://symfony.com/doc/2.8/cookbook/form/dynamic_form_modification.html#cookbook-form-events-submitted-data

谢谢

已编辑

您还应该在 ajax 数据中传递令牌值:

$data['product_form']['_token'] = $('#product_form__token').val();

你的表单在你的页面中呈现一个隐藏的token输入,你需要把它添加到你的javascript data变量中,比如data[$('#product_form_token').name()] = $('#product_form_token').val()这样它就不会丢失,你也不会收到CSRF错误。如果不是这个,请按令牌输入名称更改product_form_token

在控制器中使用$checkbox = filter_var($checkbox, FILTER_VALIDATE_BOOLEAN);其中$checkbox是表单字段,然后在表单中设置它,然后再验证、保留和刷新它。有时,对于布尔值,0 值可以被视为真值,意思是"你得到了一些东西,所以它是真的"。