Background:
I am writing a RESTful API on symfony. I want the client to be able to post to a url using the content type application/json and post a json object of form that the controller action is looking for.
Im using a pretty basic controller setup for this. Lets assume for demonstration purposes that im trying to authenticate a simple username password combo.
public function loginAction( Request $request )
{
$user = new ApiUser();
$form = $this->createForm(new ApiUserType(), $user);
if ( "POST" == $request->getMethod() ) {
$form->bindRequest($request);
if ( $form->isValid() ) {
$em = $this->getDoctrine()->getEntityManager();
$repo = $this->getDoctrine()->getRepository('ApiBundle:ApiUser');
$userData = $repo->findOneByUsername($user->getUsername());
if ( is_object($userData) ) {
/** do stuff for authenticating **/
}
else{
return new Response(json_encode(array('error'=>'no user by that username found')));
}
else{
return new Response(json_encode(array('error'=>'invalid form')));
}
}
}
Now the issue that i have, and have i have tried var_dumping this till the cows come home, is that for what ever reason symfony does not want to take the application/json content-body and use that data to populate the form data.
Form name: api_apiuser
Fields: username, password
What would be the best way to handle this type of task. I am open to suggestions as long as i can get this working. Thanks for your time with the matter.
Youll need to access the RAW request body and then use json_decode. Youll probably need to change your bindRequest
method to something like the following:
public function bindRequest(Request $request)
{
if($request->getFormat() == 'json') {
$data = json_decode($request->getContent());
return $this->bind($data);
} else {
// your standard logic for pulling data form a Request object
return parent::bind($request);
}
}
I havent really messed with SF2 yet so this is more guessing based on the API, exp. with sf1.x and things ive garnered from presentations on the framework. It might also be better to make a completely different method like bindJsonRequest
so things are a bit more tidy.
Ive actually found a similar way to fix this, AFTER checking if the method is post and before binding the request to the form i do this:
if ( "POST" === $request->getMethod() ) {
if (0 === strpos($request->headers->get('Content-Type'), 'application/json')){
$data = json_decode($request->getContent(), true);
$request->request->replace(is_array($data) ? $data : array());
}
$form->bindRequest($request);
/** Rest of logic **/
}
Yeah, what the form is waiting for during binding is an array containing keys that correspond to your ApiUser properties.
So if you send a POST request with the string:
{ username: 'user', password: 'pass' }
You will have to transform it into an array using json_decode
for example:
$data = json_decode($request->getContent()); // $request->request->get('json_param_name');
Then you bind this array to the form using $form->bind($data);
The form will update your ApiUser properties corresponding to array's keys (username, password).
If you're building a RESTful json api, I would advice you to automatize this process using serializers/transformers, like https://github.com/schmittjoh/JMSSerializerBundle/blob/master/Resources/doc/index.rst
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With