PUT请求不适用于Symfony表单和FosRest


PUT request not working with Symfony forms and FosRest

我正在尝试使用FosRest和Symfony表单编写一个简单的restful控制器,用于Symfony中的用户管理。我的应用程序由AmazonDynamoDB支持,尽管我认为这并不重要。

我的DELETE、GET和POST(新用户)都工作得很好。

我现在开始编写PUT操作(编辑用户),但它似乎不起作用。我花了很长时间把头撞在砖墙上,但我就是想不通。

为了创建PUT,我基本上复制了POST操作,但将其修改为首先加载旧对象。

在POST中,User对象自动由$form->handleRequest($request)行填充;

这似乎在PUT操作中不起作用,用户对象不会被填充/修改。我已经检查了$_REQUEST数组,并且正在提交数据。由于浏览器不支持PUT,我通过使用查询参数_method=PUT对数据进行POST来调用该操作(这对DELETE很有效,并且它正在路由到正确的位置)。

以下是我的POST操作:

public function postUsersAction(Request $request)
{
    $user = new User();
    $user->setTable($this->getTable());
    $formBuilder = $this->createFormBuilder($user, array(
        'validation_groups' => array('registration', '')))
        ->add('username', 'text')
        ->add('password', 'password')
        ->setAction($this->generateUrl('post_users'))
        ->setMethod('POST')
        ->setAttribute('validation_groups', array('registration'));
    $roles = $this->getFlattenedRoles($this->getRoles());
    $formBuilder->add('roles', 'choice', array(
        'choices'   => $roles,
        'multiple'  => true,
        'expanded'  => true
    ));
    $form = $formBuilder->add('save', 'submit')->getForm();
    $form->handleRequest($request);
    if ($form->isValid())
    {
        $user->save();
        $params = array('user' => $user);
        $view = $this->view($params, 200)
            ->setTemplate("MyRestBundle:User:newconfirm.html.twig");
        return $this->handleView($view);
    }
    $params = array('form' => $form, 'user' => $user);
    $view = $this->view($params, 400)
        ->setTemplate("MyRestBundle:User:new.html.twig");
    return $this->handleView($view);
}

这是我的PUT控制器,它没有:

public function putUserAction($slug, Request $request)
{
    $table = $this->getTable();
    $user = $table->load($slug);
    $formBuilder = $this->createFormBuilder($user)
        ->add('password', 'password')
        ->setAction($this->generateUrl('put_user', array('slug' => $slug, '_method' => 'PUT')))
        ->setMethod('POST');
    $roles = $this->getFlattenedRoles($this->getRoles());
    $formBuilder->add('roles', 'choice', array(
        'choices'   => $roles,
        'multiple'  => true,
        'expanded'  => true
    ));
    $form = $formBuilder->add('save', 'submit')->getForm();
    $form->handleRequest($request);
    if ($form->isValid())
    {
        $user->save();
        $params = array('user' => $user);
        $view = $this->view($params, 200)
            ->setTemplate("MyRestBundle:User:newconfirm.html.twig");
        return $this->handleView($view);
    }
    $params = array('form' => $form, 'user' => $user);
    $view = $this->view($params, 400)
        ->setTemplate("MyRestBundle:User:new.html.twig");
    return $this->handleView($view);
}

如有任何帮助,我们将不胜感激。

好吧,在Symfony IRC频道中得到一些帮助后,发现这不起作用的原因是代码的这一部分:

$formBuilder = $this->createFormBuilder($user)
    ->add('password', 'password')
    ->setAction($this->generateUrl('put_user', array('slug' => $slug, '_method' => 'PUT')))
    ->setMethod('POST');

由于PUT在许多浏览器中都不起作用,我试图将该方法设置为POST,并将_method=PUT作为查询参数来覆盖真正的HTTP方法。事实证明,没有必要这么做,Symfony会为你处理这一切。上面的代码现在只是:

$formBuilder = $this->createFormBuilder($user)
    ->add('password', 'password')
    ->setAction($this->generateUrl('put_user', array('slug' => $slug))
    ->setMethod('PUT');

通过这样做,Symfony实际上呈现了一个带有隐藏_method字段的POST表单——不需要手动执行任何操作。