Reputation: 670
I am stack with posting JSON data to a form in the controller. The entity is not filled in with properties that I am sending, here it's how it looks like:
// Controller
class UserApiController extends FOSRestController
{
// works fine
public function cgetAction()
{
return $this->get('model.user')->getAllUsers();
}
// works fine
public function getAction($id)
{
return $this->get('model.user')->getUserById($id);
}
// this method fails
public function postAction(Request $request)
{
$form = $this->createForm(new UserType(), new User());
$form->bind($request);
if($form->isValid())
{
die('are you valid or not??');
}
return $this->view($form, 400);
}
}
Entity looks like a regular one and form as well.
I have a test controller that sends the json data to the api:
public function testJsonPostAction()
{
$client = static::createClient();
$client->request(
'POST',
'/api/1.0/users',
array(),
array(),
array('CONTENT_TYPE' => 'application/json'),
'{"firstName": "John", "lastName": "Doe", "emailAddress": "[email protected]", "sex": "1"}'
);
var_dump($client->getResponse()->getContent());
}
And the validation:
Software\Bundle\Entity\User:
properties:
firstName:
- NotBlank: ~
- Length:
min: 2
max: 255
lastName:
- NotBlank: ~
- Length:
min: 2
max: 255
Ok, the problem is that $form is always not valid. When I dump the $form->getData() content I got my User entity but firstName, lastName etc is not filled in. Instead I got validation errors obviously but here's another but:
Why $form->bind($request) (I know it's deprecated) returns this (which is more less good):
{"code":400,"message":"Validation Failed","errors":{"children":{"firstName":{"errors":["This value should not be blank."]},"lastName":{"errors":["This value should not be blank."]},"emailAddress":{"errors":["This value should not be blank."]},"sex
":[],"locale":[]}}}
and the same code but with $form->handleRequest($request) returns this:
{"children":{"firstName":[],"lastName":[],"emailAddress":[],"sex":[],"locale":[]}}
What's the difference? Since I thought handleRequest is a replacement for bind. I tried already I think all the solutions on the Internet and every time is something different and I can't get it work. Documentation of FOSRestBundle is very poor, it says all about getting stuff, but almost nothing about posting.
Any help much appreciated.
Upvotes: 4
Views: 5187
Reputation: 511
i solved it like this:
$user = new User;
$form = $this->createForm(UserType::class, $user);
$view = View::create();
$form->submit($request->request->all());
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($user);
$em->flush();
$view->setData($form->getData());
} else {
$view->setData($form);
}
return $this->handleView($view);
Don't forget to disable CSRF validation (https://symfony.com/doc/master/bundles/FOSRestBundle/2-the-view-layer.html#csrf-validation)
fos_rest:
disable_csrf_role: ROLE_API
#disable_csrf_role: IS_AUTHENTICATED_ANONYMOUSLY #just for testing
Then you get a nice output like this:
{
"code": 400,
"message": "Validation Failed",
"errors": {
"children": {
"name": {
"errors": [
"This value should not be blank."
]
},
"role": {
"errors": [
"This value should not be blank."
]
}
}
}
}
Upvotes: 0
Reputation: 670
Since nobody replied, I am going to answer myself in this question.
First of all, sent JSON must start with form name, so instead:
{"firstName": "John", "lastName": "Doe", "emailAddress": "[email protected]", "sex": "1"
must be:
{"user": {"firstName": "John", "lastName": "Doe", "emailAddress": "[email protected]", "sex": "1"}}
In my case, form name was "user".
I have used CURL to test it:
curl -v -H "Accept: application/json" -H "Content-type: application/json" -XPOST -d "{\"user\":{\"firstName\":\"John\", \"emailAddress\": \"[email protected]\", \"password\":\"verystrongmuchpower\"}}" http://localhost.software.com/app_dev.php/api/1.0/users
Since I am testing the API with CURL, a difference in response in bind and handleRequest is gone.
I will update this answer soon if I get more conclusions.
Upvotes: 5