简体   繁体   English

Symfony2 FOSRestBundle PUT Action FORM返回空结果

[英]Symfony2 FOSRestBundle PUT Action FORM returns empty results

I am using Symfony 2.2 and the latest version of FOSRestBundle. 我正在使用Symfony 2.2和最新版本的FOSRestBundle。 So I have manage to make most of the actions work but I seem to have an issue with the FormBuilder that I am passing the Request of my PUT call in. 所以我设法让大多数动作都有效,但我似乎遇到了FormBuilder的问题,我正在通过PUT调用请求。

I have checked the request object and it comes from my Backbone.je model as it should (.save()) But after binding to the form the entity comes back with only the id which causes flush() to throw an error since required fields are not filled. 我检查了请求对象,它来自我的Backbone.je模型​​,因为它应该(.save())但是在绑定到表单后,实体返回只有id导致flush()抛出错误,因为必需的字段没有填补。

The action in the Controller: 控制器中的操作:

header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS ');
header('Allow GET, POST, PUT, DELETE, OPTIONS ');
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: Content-Type, *');

use FOS\RestBundle\Controller\FOSRestController;
use FOS\RestBundle\Controller\Annotations as Rest;
use FOS\RestBundle\Routing\ClassResourceInterface;
use FOS\Rest\Util\Codes;
use Symfony\Component\HttpFoundation\Request;
use Greenthumbed\ApiBundle\Entity\Container;
use Greenthumbed\ApiBundle\Form\ContainerType;

class ContainerController extends FOSRestController implements ClassResourceInterface
{
/**
 * Put action
 * @var Request $request
 * @var integer $id Id of the entity
 * @return View|array
 */
public function putAction(Request $request, $id)
{
    $entity = $this->getEntity($id);
    $form = $this->createForm(new ContainerType(), $entity);
    $form->bind($request);

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

        return $this->view(null, Codes::HTTP_NO_CONTENT);
    }

    return array(
        'form' => $form,
    );
}

/**
 * Get entity instance
 * @var integer $id Id of the entity
 * @return Container
 */
protected function getEntity($id)
{
    $em = $this->getDoctrine()->getManager();

    $entity = $em->getRepository('GreenthumbedApiBundle:Container')->find($id);

    if (!$entity) {
        throw $this->createNotFoundException('Unable to find Container entity');
    }

    return $entity;
}

The Form that is called: 被称为的表格:

namespace Greenthumbed\ApiBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class ContainerType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name')
            ->add('description')
            ->add('isVisible')
            ->add('type')
            ->add('size')
            ->add('creationDate')
            ->add('userId')
        ;
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Greenthumbed\ApiBundle\Entity\Container',
            'csrf_protection' => false,
        ));
    }

    public function getName()
    {
        return 'greenthumbed_apibundle_containertype';
    }
}

I have tried everything so far but I am fairly new with Symfony and I cannot understand why the $entity does not contain the values received by the request. 到目前为止我已经尝试了所有内容,但我对Symfony还是比较新的,我无法理解为什么$实体不包含请求收到的值。

FYI: I have tried doing it manually as in instantiating a Container class with the ID of the request and putting use the setters to input values into it and it works just fine, I just want to do things the right way as Symfony suggests it should be done. 仅供参考:我尝试手动操作,例如在实例化具有请求ID的Container类,并使用setter将值输入到其中并且它工作正常,我只是想以正确的方式做事情,因为Symfony建议它应该完成。

Thank you very much in advance. 非常感谢你提前。

Try changing the following line in putAction: 尝试在putAction中更改以下行:

$form = $this->createForm(new ContainerType(), $entity);

to: 至:

$form = $this->createForm(new ContainerType(), $entity, array('method' => 'PUT'));

I think you are experiencing the same problem I had: The mistake is in the name of the Form. 我认为你遇到了同样的问题:错误在于Form的名称。

In your Form definition the name is "greenthumbed_apibundle_containertype". 在表单定义中,名称为“greenthumbed_apibundle_containertype”。 public function getName() { return 'greenthumbed_apibundle_containertype'; public function getName(){return'greenthumbed_apibundle_containertype'; } }

So to bind a request to this form the json should have looked like this: 因此,要将请求绑定到此表单,json应该如下所示:

{"greenthumbed_apibundle_containertype": [{"key": "value"}]}

Since Backbone .save() method ship this kind of json 由于Backbone .save()方法提供了这种json

{"key":"value","key2":"value2"}

you have to remove the name from the Form: 你必须从表单中删除名称:

public function getName()
{
    return '';
}

In general if you want to post a json with a placeholder like 一般来说,如果你想发布一个像占位符一样的json

"something":{"key":"value"}

your form name must be exactly "something" 你的表格名称必须是“某事”

from my own question here 从我自己的问题在这里

Use the ParamConverter to have your Entity injected as an argument in your method automatically. 使用ParamConverter自动将您的实体作为参数注入方法中。

use Greenthumbed\ApiBundle\Entity\Container;

// ...

public function putAction(Request $request, Container $container)
{
    $form = $this->createForm(new ContainerType(), $container);
    $form->bind($request);

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

        // Entity already exists -> no need to persist!
        // $em->persist($entity);   

        $em->flush();

        return $this->view(null, Codes::HTTP_NO_CONTENT);
    }

    return array('form' => $form);
}

see http://symfony.com/doc/current/cookbook/routing/method_parameters.html 请参阅http://symfony.com/doc/current/cookbook/routing/method_parameters.html

Unfortunately, life isn't quite this simple, since most browsers do not support sending PUT and DELETE requests. 不幸的是,生活并不那么简单,因为大多数浏览器不支持发送PUT和DELETE请求。 Fortunately Symfony2 provides you with a simple way of working around this limitation. 幸运的是,Symfony2为您提供了一种解决此限制的简单方法。 By including a _method parameter in the query string or parameters of an HTTP request, Symfony2 will use this as the method when matching routes. 通过在查询字符串中包含_method参数或HTTP请求的参数,Symfony2将在匹配路由时将其用作方法。 Forms automatically include a hidden field for this parameter if their submission method is not GET or POST. 如果表单的提交方法不是GET或POST,则表单会自动包含此参数的隐藏字段。 See the related chapter in the forms documentation for more information. 有关详细信息,请参阅表单文档中的相关章节。

and http://symfony.com/doc/current/book/forms.html#book-forms-changing-action-and-method http://symfony.com/doc/current/book/forms.html#book-forms-changing-action-and-method

If the form's method is not GET or POST, but PUT, PATCH or DELETE, Symfony2 will insert a hidden field with the name "_method" that stores this method. 如果表单的方法不是GET或POST,而是PUT,PATCH或DELETE,Symfony2将插入一个名为“_method”的隐藏字段,用于存储此方法。 The form will be submitted in a normal POST request, but Symfony2's router is capable of detecting the "_method" parameter and will interpret the request as PUT, PATCH or DELETE request. 表单将在普通POST请求中提交,但Symfony2的路由器能够检测“_method”参数,并将请求解释为PUT,PATCH或DELETE请求。 Read the cookbook chapter "How to use HTTP Methods beyond GET and POST in Routes" for more information. 有关更多信息,请阅读食谱章节“如何在路由中使用GET和POST之外的HTTP方法”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM