Symfony2 FOSRestBundle PUT Action FORM返回空结果


Symfony2 FOSRestBundle PUT Action FORM returns empty results

我正在使用Symfony 2.2和最新版本的FOSRestBundle。所以我已经设法使大部分的行动工作,但我似乎有一个问题与FormBuilder,我正在传递我的PUT调用的请求。

我已经检查了请求对象,它来自我的主干。但是在绑定到表单之后,实体只返回id,这会导致flush()抛出一个错误,因为必需的字段没有填充。

控制器中的动作:

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;
}

被称为

的表单

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';
    }
}
到目前为止,我已经尝试了所有的东西,但我是Symfony的新手,我无法理解为什么$entity不包含请求收到的值。

仅供参考:我已经尝试过手动做它在实例化一个容器类与请求的ID和使用设置器输入值到它,它工作得很好,我只是想做事情的正确方式作为Symfony建议它应该做的。

提前谢谢你。

尝试更改putAction中的以下行:

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

:

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

我想你遇到了和我一样的问题:错误出在表单的名称上。

在你的表单定义的名称是"greenthumbed_apibundle_containertype"。getName(){返回"greenthumbed_apibundle_containertype";}

要将请求绑定到这个表单json应该是这样的:
{"greenthumbed_apibundle_containertype": [{"key": "value"}]}

因为Backbone .save()方法自带这种json

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

你必须从表单中删除名字:

public function getName()
{
    return '';
}

一般来说,如果你想发布带有占位符的json,比如

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

你的表单名必须恰好是"something"

来自我自己的问题

使用参数转换器将实体作为参数自动注入到方法中。

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

参见http://symfony.com/doc/current/cookbook/routing/method_parameters.html

不幸的是,生活并没有这么简单,因为大多数浏览器都是这样不支持发送PUT和DELETE请求。幸运的是Symfony2为您提供一种绕过此限制的简单方法。通过在查询字符串或参数中包含_method参数HTTP请求,Symfony2将在匹配时使用此方法路线。表单自动为该参数包含一个隐藏字段如果它们的提交方法不是GET或POST。参见相关章节在表单文档中获取更多信息。

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

如果表单的方法不是GET或POST,而是PUT, PATCH或DELETE,Symfony2将插入一个名为"_method"的隐藏字段存储此方法。表单将以普通的POST方式提交但是Symfony2的路由器能够检测到"_method"参数,并将请求解释为PUT、PATCH或DELETE请求。阅读烹饪书章节"如何使用GET之外的HTTP方法"