I'm trying to validate in my controller with form object, but it doesn't work. It is my post method of my controller:
public function postAction(Request $request) {
$entity = new entity();
$form = $this->createForm(new entityType(), $entity);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->get('doctrine_mongodb')->getManager();
$em->persist($entity);
$em->flush();
return $this->redirectView(
$this->generateUrl(
'get_entity',
array('id' => $entity->getId())
)
);
}
return array(
'form' => $form,
);
}
I send this data:
{"name":"Hello word","description":"I am a hello word"}
With this headers:
Accept: : application/json
Content-Type: : application/json
The result is that nothing is saved on DB and the response ( with status 200) that I get:
{"children":{"name":[],"description":[]}}
I test to change $form->handleRequest($request) to $form->bind($request);
There are some changes. For example, the new entity is saved on BD but only with id (because is autoincrement).
Then, I thought that the $request doesn't get the data. But yes, the data is on $request. if I add this line I can get the json object:
$content = $request->getContent();
I am using: Symfony2.4.2. What is the problem?
Many thanks.
The issue here is that your form is created with a root name equal to the name of your form type (it is the behavior of the createForm shortcut). So your method currently expects the following data (assuming the name of your form type is my_entity):
{
"my_entity": {"name":"Hello word","description":"I am a hello word"}
}
In an API, you generally don't want to have a root name on the form. Doing it requires passing the name of your form explicitly (and empty string in this case) instead of relying on the default convention:
$form = $this->get('form.factory')->createNamed('', new entityType(), $entity);
I tested both solutions but they doesn't work for me. I am using mongodbBundle, I don't know if that could be a problem (I think not)
This is my EntityType:
class EntityType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('description')
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'PieceCake\APIBundle\Document\Entity',
'csrf_protection' => false,
));
}
public function getName()
{
return 'entity';
}
}
I closed the issue, but was a mistake. I have reopened it. Sorry for that.
be careful when using entity as your type name. this name is already used by a core type, so it will cause weird bugs.
Is the result exactly he same when changing the code according to my comments, or is there some difference ?
Yes, I have the same result. I don't use this name of the FormType, I change it only for copy paste here.
can you check the value of $form->isSubmitted() after the call to handleRequest() ?
also note that my 2 code blocks are exclusive. Changing both the submitted data and the expectation will not work (the issue will be the same in the opposite way). You should either submit the data with the top-level key, or tell Symfony that you don't want it, but not both
$form->isSubmitted() is empty. I get nothing.
This method of class FormType represent the name that I should put in the json:
public function getName()
{
return 'this_is_the_name';
}
Like this:
{
"this_is_the_name": {"name":"Hello word","description":"I am a hello word"}
}
it cannot be empty. It is always true or false (quick reminder, print_r is not a good debugging function, as its output can be the same for many different values)
I done this, and alwaysget else.
$form->handleRequest($request);
if ( $form->isSubmitted() ) $a = 'if';
else $a = "else";
return $this->render(
'PieceCakeAPIBundle:Default:index.html.twig',
array('name' => $a)
);
Also, I done this, and $a = nothing.
$form->handleRequest($request);
$a= $form->isSubmitted() );
return $this->render(
'PieceCakeAPIBundle:Default:index.html.twig',
array('name' => $a)
);
@webmozart do you have a hint here?
You can use two approaches.
/**
* Creates use profiles
* @ApiDoc(
* resource=true,
* description="Creates user profile",
* input="Foo\BarBundle\Form\Type\ProfileType",
* output="Foo\BarBundle\Entity\User\Profile",
* statusCodes={
* 201="Returned when successful",
* 401="Returned when trying to create non authenticated",
* 422="Returned when the profile validation failed"
* }
* )
*
* @param Request $request
* @return View
*/
public function createAction(Request $request)
{
$profile = new User\Profile($this->getUser());
$form = $this->createForm(new ProfileType(), $profile);
$form->submit(($request->request->get($form->getName())));
if ($form->isValid()) {
$this->get('foo.user.manager')->saveProfile($profile);
return View::create($profile, Codes::HTTP_CREATED);
}
return View::create($form);
}
Second option:
if (!$form->isValid()) {
if (!$form->isSubmitted()) {
$form->submit([]);
}
return View::create($form);
}
If you send invalid data, then the form will not be submitted and the response will be
{"children":{"name":[],"description":[]}}
@lsmith77 @pacorampas This is not fos rest bundle issue, so i would say it can be closed.
@defrag But maybe a cookbook entry would be helpful in case others struggling with the same problem and overlook this issue. :smile:
Closing because @defrag explained it correctly. This is not an implementation problem but a usage problem. Also it seems that the rest bundle can actually handle this: https://github.com/FriendsOfSymfony/FOSRestBundle/blob/master/View/ViewHandler.php#L498
When the form is not submitted because of wrong data, the view is marked as validation failed.
Most helpful comment
You can use two approaches.
Second option:
If you send invalid data, then the form will not be submitted and the response will be
{"children":{"name":[],"description":[]}}
@lsmith77 @pacorampas This is not fos rest bundle issue, so i would say it can be closed.