8

我正在使用 Symfony 2.2 和最新版本的 FOSRestBundle。因此,我设法使大多数操作起作用,但我似乎对 FormBuilder 有问题,我正在传递我的 PUT 调用的请求。

我已经检查了请求对象,它应该来自我的 Backbone.je 模型(.save())但是在绑定到表单后,实体返回的只有 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 实例化一个 Container 类,并使用 setter 向其中输入值,它工作得很好,我只想按照 Symfony 建议的正确方式做事做完了。

非常感谢您提前。

4

4 回答 4

8

尝试在 putAction 中更改以下行:

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

至:

$form = $this->createForm(new ContainerType(), $entity, array('method' => 'PUT'));
于 2013-07-23T01:36:56.847 回答
6

我认为您遇到了与我相同的问题:错误在于表单的名称。

在您的表单定义中,名称是“greenthumbed_apibundle_containertype”。公共函数 getName() { return 'greenthumbed_apibundle_containertype'; }

因此,要将请求绑定到此表单,json 应该如下所示:

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

由于 Backbone .save() 方法提供这种 json

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

您必须从表单中删除名称:

public function getName()
{
    return '';
}

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

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

您的表单名称必须完全是“某物”

从我自己的问题here

于 2013-12-14T15:19:08.637 回答
0

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

不幸的是,生活并非如此简单,因为大多数浏览器不支持发送 PUT 和 DELETE 请求。幸运的是 Symfony2 为您提供了一种解决此限制的简单方法。通过在查询字符串或 HTTP 请求的参数中包含 _method 参数,Symfony2 将在匹配路由时使用它作为方法。如果表单的提交方法不是 GET 或 POST,则表单会自动包含此参数的隐藏字段。有关详细信息,请参阅表单文档中的相关章节。

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

如果表单的方法不是 GET 或 POST,而是 PUT、PATCH 或 DELETE,Symfony2 将插入一个名为“_method”的隐藏字段来存储该方法。表单将在普通的 POST 请求中提交,但 Symfony2 的路由器能够检测“_method”参数并将请求解释为 PUT、PATCH 或 DELETE 请求。阅读食谱章节“如何在路由中使用 GET 和 POST 之外的 HTTP 方法”以获取更多信息。

于 2013-11-28T19:23:41.583 回答
0

使用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);
}
于 2013-06-09T05:21:19.587 回答