表单提交时出错:CSRF令牌无效.请尝试重新提交表单

sch*_*kxx 1 forms symfony tag-it twitter-bootstrap pagedown

我一直在尝试提交一个表单,将一个Question对象添加到db中.

但每次我这样做,错误"CSRF令牌无效.请尝试重新提交表单"显示.

在我的表单的内容字段中,我附加了这个插件,这是一个与Stack Overflow相同的编辑器.

在我的表单的标记字段中,我已将此附加标记自动完成.

这是我的控制器代码:

/**
 * Creates a new Question entity.
 *
 * @Route("/ask", name="question_create")
 * @Method("POST")
 * @Template("VerySoftAskMeBundle:Question:ask.html.twig")
 */
public function createAction(Request $request) {
    $entity = new Question();
    $form = $this->createCreateForm($entity);
    $tags = $this->getDoctrine()->getRepository('VerySoftAskMeBundle:Tag')->findAll();
    date_default_timezone_set('Asia/Manila');
    $entity->setDateOfPost(new \DateTime());

    $entity->setOwner($this->getUser());

        $form->handleRequest($request);

        if ($form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $em->persist($entity);
            $em->flush();

            return $this->redirect($this->generateUrl('question_show', array('id' => $entity->getId())));
        }


    return array(
        'entity' => $entity,
        'form' => $form->createView(),
        'tags' => $tags
    );
}

/**
 * Creates a form to create a Question entity.
 *
 * @param Question $entity The entity
 *
 * @return Form The form
 */
private function createCreateForm(Question $entity) {
    $form = $this->createForm(new QuestionType(), $entity, array(
        'action' => $this->generateUrl('question_create'),
        'method' => 'POST',
        'em' => $this->getDoctrine()->getEntityManager()
    ));

    $form->add('submit', 'submit', array('label' => 'Ask'));

    return $form;
}

/**
     * 
     * @Route("/ask", name="ask")
     * @Security( "has_role( 'ROLE_USER' )" )
     * @Method("GET")
     * @Template
     */
    public function askAction() {

        $tags = $this->getDoctrine()->getRepository('VerySoftAskMeBundle:Tag')->findAll();
        $entity = new Question();
        $form = $this->createCreateForm($entity);

        return array(
            'entity' => $entity,
            'form' => $form->createView(),
            'tags' => $tags
        );
    }
Run Code Online (Sandbox Code Playgroud)

我为我的标记字段创建了一个Data Transformer,它将输入标记转换为标记对象.

class TagTransFormer implements DataTransformerInterface {

/**
 * @var ObjectManager
 */
private $om;

/**
 * @param ObjectManager $om
 */
public function __construct(ObjectManager $om) {
    $this->om = $om;
}

/**
 * Transforms an object (issue) to a string (number).
 *
 * @return ArrayCollection
 */
public function transform($tags) {

    return $tags;
}

/**
 * Transforms a string (number) to an object (issue).
 *
 * @param  string $number
 *
 * @return ArrayCollection
 *
 * @throws TransformationFailedException if object (issue) is not found.
 */
public function reverseTransform($ids) {

    $tags = array();

    if (!$ids) {
        return null;
    }

    $repo = $this->om
            ->getRepository('VerySoftAskMeBundle:Tag');

    $idsArray = explode(",", $ids);
    foreach ($idsArray as $id) {
        $tags[] = $repo->findOneByName($id);
    }
    return $tags;
}
}
Run Code Online (Sandbox Code Playgroud)

这是我的表单类:

class QuestionType extends AbstractType {

/**
 * @param FormBuilderInterface $builder
 * @param array $options
 */
public function buildForm(FormBuilderInterface $builder, array $options) {

    $entityManager = $options['em'];
    $transformer = new TagTransFormer($entityManager);

    $builder
            ->add('title', 'text')
            ->add('content', 'textarea')
            ->add($builder->create('tags', 'text')
                    ->addModelTransformer($transformer)
    );
}

/**
 * @param OptionsResolverInterface $resolver
 */
public function setDefaultOptions(OptionsResolverInterface $resolver) {
    $resolver->setDefaults(array(
                'data_class' => 'VerySoft\AskMeBundle\Entity\Question'
            ))
            ->setRequired(array(
                'em',
            ))
            ->setAllowedTypes(array(
                'em' => 'Doctrine\Common\Persistence\ObjectManager',
    ));
}

/**
 * @return string
 */
public function getName() {
    return 'verysoft_askmebundle_question';
}
}
Run Code Online (Sandbox Code Playgroud)

我的树枝模板:

<div id="askDiv" style="padding-bottom: 90px;">
        {{ form_start(form, { 'attr' : { 'novalidate' : 'novalidate', 'class' : 'col-md-offset-3 form-control-static col-md-7' } }) }}
<div class="col-lg-12" style="padding: 0px; margin-bottom: 30px;">
    <span class="askLabels col-lg-1 text-left">{{ form_label(form.title) }}</span>
            {{form_widget(form.title, { 'attr' : { 'class' : 'form-control col-lg-11' } })}}
</div>
        {{ form_widget(form.content, { 'attr' : { 'class' : 'col-lg-12' } }) }}
<div class="col-lg-12" style="padding: 0px; margin-top: 20px;">
    <label class="col-lg-1 text-left askLabels" for="tagField">Tags</label>

    <div class="col-lg-8">
        {{ form_widget(form.tags) }}
    </div>
    {% if app.user.reputation >= 100 %}
    <a id="addTag" title="Add New Tag" data-toggle="tooltip modal" data-placement="left" class="col-lg-3" href="#"><i class="fa fa-plus-circle"></i></a>
    <div id="mymodal" class="modal fade bs-example-modal-lg" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel" aria-hidden="true">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
                    <h4 class="modal-title" id="myModalLabel">Add New Tag</h4>
                </div>
                <div class="modal-body">
                    <label for="tagName">Tag Name: </label>
                    <input id="tagName" class="form-control" type="text"/>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
                    <button type="button" class="btn btn-primary">Add Tag</button>
                </div>
            </div>
        </div>
    </div>

    {% endif %}


</div>
<div style="margin-top: 20px; ">
        {{ form_widget(form.submit, { 'attr' : { 'class' : 'col-md-offset-4 col-md-4  btn btn-primary' } }) }}
</div>

<p>
    title error{{ form_errors(form.title) }}
</p>
<p>
    content error{{ form_errors(form.content) }}
</p>
<p>
    tag error{{ form_errors(form.tags) }}
</p>
<p>
    form error{{ form_errors(form) }}
</p>
Run Code Online (Sandbox Code Playgroud)

脚本:

$(document).ready(function(){
$("textarea").pagedownBootstrap();

    var zeTags = ["{{ tags|join('", "')|raw }}"];
    $('#verysoft_askmebundle_question_tags').tagit({
        availableTags: zeTags,
        tagLimit: 5,
        beforeTagAdded: function(event, ui) {
            if ($.inArray(ui.tagLabel, zeTags) == -1)
                return false;
        }
    });
});
Run Code Online (Sandbox Code Playgroud)

Don*_*sto 5

你错过了

{{ form_rest(form) }}
Run Code Online (Sandbox Code Playgroud)

Symfony2有一种机制可以帮助防止跨站点脚本:它们生成一个必须用于表单验证的CSRF令牌.在这里,在您的示例中,您没有显示(因此不提交)它form_rest(form).基本上,form_rest(form)将"渲染"您之前未呈现的每个字段,但这些字段包含在您传递给视图的表单对象中.CSRF令牌是其中一个值.