Posting JSON objects to Symfony 2

PhpAjaxJsonSymfony

Php Problem Overview


I'm working on a project using Symfony 2, I've built a bundle to handle all my database services which passes JSON data back and forward.

My Problem/Question:

  • Is it possible to post a straight up JSON object? Currently I'm spoofing a normal form post for my ajax calls by giving the object a name json={"key":"value"} if I don't give it a name I can't seem to get the data from the Symfony request object $JSON = $request->request->get('json');

  • I want to be able to use the one service bundle to handle both data coming from AJAX calls, or a normal Symfony form. Currently I'm taking the submitted Symfony form, getting the data then using JSON_ENCODE, I just can't work out how to post the data through to my services controller which is expecting request data.

To summarise:

  • I want Symfony to accept a JSON post object rather than a form.

  • I want to pass the JSON object between controllers using Request/Response

If I'm going about this all wrong, feel free to tell me so!

Php Solutions


Solution 1 - Php

If you want to retrieve data in your controller that's been sent as standard JSON in the request body, you can do something similar to the following:

public function yourAction()
{
    $params = array();
    $content = $this->get("request")->getContent();
    if (!empty($content))
    {
        $params = json_decode($content, true); // 2nd param to get as array
    }
}

Now $params will be an array full of your JSON data. Remove the true parameter value in the json_decode() call to get a stdClass object.

Solution 2 - Php

I wrote method to get content as array

protected function getContentAsArray(Request $request){
    $content = $request->getContent();

    if(empty($content)){
        throw new BadRequestHttpException("Content is empty");
    }

    if(!Validator::isValidJsonString($content)){
        throw new BadRequestHttpException("Content is not a valid json");
    }

    return new ArrayCollection(json_decode($content, true));
}

And I use this method as shown below

$content = $this->getContentAsArray($request);
$category = new Category();
$category->setTitle($content->get('title'));
$category->setMetaTitle($content->get('meta_title'));

Solution 3 - Php

javascript on page:

function submitPostForm(url, data) {
	var form 				= document.createElement("form");
		form.action			= url;
		form.method			= 'POST';
		form.style.display	= 'none';
	
	//if (typeof data === 'object') {}

	for (var attr in data) {
		var param 		= document.createElement("input");
			param.name 	= attr;
			param.value	= data[attr];
			param.type 	= 'hidden';
		form.appendChild(param);
	}

	document.body.appendChild(form);
	form.submit();
}

after some event (like a click on "submit"):

// products is now filled with a json array
var products = jQuery('#spreadSheetWidget').spreadsheet('getProducts');
var postData = {
'action':	action,
'products':	products
}
submitPostForm(jQuery('#submitURLcreateorder').val(), postData);

in the controller:

   /**
    * @Route("/varelager/bestilling", name="_varelager_bestilling")
    * @Template()
    */
   public function bestillingAction(Request $request) {
       $products   = $request->request->get('products', null); // json-string
       $action     = $request->request->get('action', null);

       return $this->render(
           'VarelagerBundle:Varelager:bestilling.html.twig',
           array(
               'postAction' => $action,
               'products' => $products
           )
       );
   }

in the template (bestilling.html.twig in my case):

  {% block resources %}
       {{ parent() }}
       <script type="text/javascript">
       jQuery(function(){
           //jQuery('#placeDateWidget').placedate();
           {% autoescape false %}
           {% if products %}
   
           jQuery('#spreadSheetWidget').spreadsheet({
               enable_listitem_amount: 1,
               products: {{products}}
           });
           jQuery('#spreadSheetWidget').spreadsheet('sumQuantities');
           {% endif %}
           {% endautoescape %}
   
       });
       </script>
   {% endblock %}

Alrite, I think that's what you wanted :)

EDIT To send something without simulating a form you can use jQuery.ajax(). Here is an example in the same spirit as above which will not trigger a page refresh.

jQuery.ajax({
	url:		jQuery('#submitURLsaveorder').val(),
	data:		postData,
	success:	function(returnedData, textStatus, jqXHR ){
		jQuery('#spreadSheetWidget').spreadsheet('clear');
		window.alert("Bestillingen ble lagret");
		// consume returnedData here
                    
	},
	error:		jQuery.varelager.ajaxError, // a method
	dataType:	'text',
	type:		'POST'
});

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiongregView Question on Stackoverflow
Solution 1 - PhprichsageView Answer on Stackoverflow
Solution 2 - PhpFarid MovsumovView Answer on Stackoverflow
Solution 3 - PhpЯрослав РахматуллинView Answer on Stackoverflow