I am building a REST API in Symfony using FOSRestBundle and I've stumbled upon a problem which seems to be trivial, but I can't find a nice solution.
I want to create a controller method to handle PATCH requests:
/**
* @param Article $article
* @param Request $request
*
* @Patch("/articles/{slug}")
* @ParamConverter("article", converter="doctrine.orm")
*
* @return Response
*/
public function patchAction(Article $article, Request $request)
{
$form = $this->createForm(new ArticleType(), $article);
$form->handleRequest($request);
if ($form->isValid()) {
$entityManager = $this->get('doctrine.orm.entity_manager');
$entityManager->merge($article);
$entityManager->flush();
$view = $this->view($article)
->setTemplate('MyBundle::articleSubmit.html.twig')
->setTemplateVar('article')
;
return $this->handleView($view);
}
$view = $this->view($form)
->setTemplate('MyBundle::articleForm.html.twig')
->setTemplateVar('form')
->setTemplateData(array('article' => $article))
;
return $this->handleView($view);
}
I've configured form type like this, setting method
option to PATCH
:
namespace MyBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ArticleType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('content', 'textarea');
}
public function getName()
{
return '';
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'MyBundle\Entity\Article',
'method' => 'PATCH',
));
}
}
When I want to see this working, everything goes fine as long as I make a real PATCH
request (for example using Open HttpRequester). But as most browsers support only GET and POST method, Symfony makes a trick adding _method
parameter to regular POST
request, and that's where my problem begins, because when testing this in browser I get the message:
This form should not contain extra fields.
This is obviously because ArticleType::getName()
returns empty string, but I would like my request parameters look more like content=foo
than like article[content]=foo
, as it's supposed in REST API. That's why I want this method to return blank value.
This works normally either when I change the action to POST
, or when I set the form's name, or when I make a real PATCH
request, but not when I'm sending a POST
request with _method
parameter.
I've managed to solve this problem creating a body listener that removes fields having names prefixed by _
, but that's more a dirty hack than a nice and clean solution.
I'm sure there must be some better workaround, thank you in advance for any help.