jquery cant transform json response - php

I'm using jquery with the form plugin to handle the submit, but when the client receive the server response it cant pass it to a json object:
var options = {
success: showResponse,
dataType: 'json',
error: errorhandler
};
$('#UserEditForm').ajaxForm(options);
The server response is generate with the _json_encode_ php function.
When I submit the form, always the errorhandler function is called and I check the response with firebug it comes with some kind of a space after the first "{"
" {"status":1"}"
, that with utf-8 encode and something like:
"{"status":1}"
with iso-8859-1.
Thanks!!

Do you send headers with your server reply?
Otherwise, try:
header('Content-type: application/json');
Also, I've had problems with jQuery not reading some large chunks of data in JSON correctly, and I used the parse method from json.org:
https://github.com/douglascrockford/JSON-js/blob/master/json2.js

Related

Ajax get shopping cart on page load

I want to load the shopping cart whenever the page is loaded but nothing happens. The console log is not telling me anything either. I have a post to cart system that works fine, so I cant figure out why this doesnt work.
I am using Laravel with a shopping cart plugin.
$(document).ready(function() {
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
type: 'get',
url: '{{route("getCart")}}',
error: function(data) {
var errors = data.responseJSON;
console.log(errors);
},
dataType: 'json',
success: function(data) {
$('#cartResult').html(data.cartCount)
},
});
});
public function cartGet()
{
$cartCount = Cart::content() - > count();
$data = array('cartCount' => $cartCount);
echo json_encode($data);
}
Try return json_encode($data); instead of echo.
You can also avoid json_encode and just use return $data;.
Simply return $data, laravel will place the correct header in response.
if you return json_endode($data) a Content-type: text/plain header will be placed,
if you return $data (which is a structure) laravel will json_encode under the hood and place a Content-type: application/json header.
your code should look like this:
public function cartGet()
{
return ['cartCount' => Cart::content()->count()];
}
It might be because in your $.ajax call you've set dataType: 'json'
From the docs:
As of jQuery 1.5, jQuery can convert a dataType from what it received
in the Content-Type header to what you require. For example, if you
want a text response to be treated as XML, use "text xml" for the
dataType. You can also make a JSONP request, have it received as text,
and interpreted by jQuery as XML: "jsonp text xml". Similarly, a
shorthand string such as "jsonp xml" will first attempt to convert
from jsonp to xml, and, failing that, convert from jsonp to text, and
then from text to xml.
When you echo json_encode(), it sends the data straight to the php output stream buffer and Laravel doesn't know that it needs to add a Content-Type: application/json header to its response. Without it, maybe jQuery needs the dataType to be "text json"?
As others have mentioned, you can return $data from your controller. Laravel will automatically cast your array to json, and it will also set the appropriate Content-Type headers. Maybe try that first?

When to use header('Content-Type: application/json') in PHP

I've been trying to figure out what's really the usage of header('Content-Type: application/json') in php scripts and I've found different questions and answers on stackoverflow about this subject but I still don't completely get it...
So here's the question : I've seen in some php projects this line of code, and I'm trying to understand
if this is used when another web page is calling this actual script (with ajax for example) so that the calling page can get a json from the php page
OR
if this script means that the php page is going to deal with json sent from another web page. Or maybe something else ???
Another thing that could help me if answered, lately I've been retrieving json from a resource (external url) with cURL and I had to put this header (Content-type:application/json) in the request. Did I send this header to the exertnal resource or was this MY header so that I can deal with the returned json ?
thanks
Ok for those who are interested, I finally figured out that header('Content-Type: application/json') is used when another page is calling the php script, so that the other page can automatically parse the result as json.
For instance i have in my test.php :
header('Content-type: application/json; charset=utf-8');
$arr = array ('a'=>1,'b'=>2,'c'=>3,'d'=>4,'e'=>5);
echo json_encode($arr); // {"a":1,"b":2,"c":3,"d":4,"e":5}
and in my main.js
function test() {
$.ajax({
url: 'test.php',
type: 'GET',
//dataType: 'html',
success: function (response) {
alert(response);
}
});
};
When I dont have dataType set to "json" or when I don't have the header in my test.php, the alert gives {"a":1,"b":2,"c":3,"d":4,"e":5} which is a string (tried with typeof(response), and when I have this header, or dataType:"json", I get [object Object] from the alert. So this header function is there to indicate to the calling pages which type of data it gives back, so that you can know how to deal with it. In my script, if I didn't have header('Content-Type: application/json'), I would have to parse the response in the javascript like this : JSON.parse(response) in order to make it a json, but with that header, I already have a json object, and I can parse it to html with jSON.stringify(response).
You should always set the Content-Type for any HTTP response to describe what you're serving in that response.
Whether it's JSON or something else, and whether it's for an AJAX request or any other kind of request.
You should also set the Content-Type for any request to describe your POST payload.
In PHP, if you don't specify the Content-Type header in the script, it will default to whatever you've configured default-mimetype to be in your php.ini file which is usually text/html.
Calling header('Content-Type: application/json') will override that default setting so that the script will respond with that Content-Type when requested.
Also, when calling curl with a Content-type:application/json header, you're specifying the content type for your request body and not for the expected reponse.
W3 Description For the Content-Type
The purpose of the Content-Type field is to describe the data contained in the body fully enough that the receiving user agent can pick an appropriate agent or mechanism to present the data to the user, or otherwise deal with the data in an appropriate manner.
Shortly speaking, just to inform the receiver what kind of data he received and consume it accordingly.

Angularjs $http post didn't pass param?

I've been debugging this for hours. Tried to set the header etc but no luck!
My controller
$http({
url: 'http://myphp.php/api.php',
method: "POST",
data: {'wtf':'test'}
})
.then(function(response) {
console.log(response);
},
function(response) { // optional
// failed
}
);
and my php
<?php
echo "test";
echo $_POST["wtf"];
?>
In my network tab this is how it look like
Not sure what's wrong man, really exhausted, I'm stuck for hours! Why my $_POST['wtf] didn't echo?
$http is serializing the data to JSON in the request body but PHP's $_POST is looking for key/values parsed from posted form data. These are two different mechanisms for posting data so you need to choose one and use that mechanism on both sides.
You have two options to solve this:
In your PHP code, parse the request body as JSON data and then use that object to retrieve your data. See this StackOverflow question for more information.
Modify your $http request to post the data as form data. See this StackOverflow question for more information.
$http.post (by default) does not send the data as key/value pairs. It sends it as post request.
Therefore, in your php script you should consume it like this:
$input = file_get_contents('php://input');
And then parse it like this:
$data = json_decode($input, true);

Ajax call with contentType: 'application/json' not working

I have an ajax call, that sends form data to a php function. Since I read a lot that using contentType: 'application/json' is best practice I wanted to give it a try as well. But unfortunately my script doesn't return anything when I use it. If I remove it, the script does what it is supposed to do.
Do you have any idea what the reason might be and why? Thank you!
$('#Form').submit(function(e) {
e.preventDefault();
var content = $(this).serialize() + "&ajax=1";
$.ajax('app/class/controller/contactForm.php', {
type: "POST",
//contentType: 'application/json',
dataType: 'json',
data: content,
success: function(result) {
console.log(result);
}
});
})
and my PHP:
if(isset($_POST['ajax']) && $_POST['ajax'] === '1') {
echo json_encode(validateForm($_POST));
}
When using contentType: 'application/json' you will not be able to rely on $_POST being populated. $_POST is only populated for form-encoded content types.
As such, you need to read your data from PHP raw input like this:
$input = file_get_contents('php://input');
$object = json_decode($input);
Of course if you want to send application/json you should actually send JSON, which you are not doing. You either need to build the object serialization to JSON directly, or you need to do something like this - Convert form data to JavaScript object with jQuery - to serialize the object from the form.
Honestly in your case, since you are dealing with form data, I don't quite think the use case for using application/json is there.
The best practice you refer to is about the server script setting the Content-Type for JSON to "application/json":
Header('Content-Type: application/json; charset=UTF8');
This is because otherwise a default Content-Type will be sent, often a catch-all text/html, and this could lead to an incomprehension with the client.
If you do not specify yourself a Content-Type in the jQuery request, jQuery will determine the most appropriate one. The problem here is that you were sending a POST form, for which the default Content-Type set by jQuery is application/x-www-form-urlencoded, which tells PHP to decode the data as POST fields and populate $_POST. Your script would have then recovered its parameters from $_POST (or maybe $_REQUEST).
By changing it to application/json, $_POST will no longer be populated, the receiving script operation won't receive the parameters where it was expecting to, and the operation breaks.
So you either need to:
not specify the Content-Type yourself (better, IMHO)
set a Content-Type of application/x-www-form-urlencoded; charset=UTF-8
set a Content-Type of application/json; charset=UTF-8 and modify the script to parse the POST stream and decode the JSON data; see this answer.
The third option requires proper handling of php://input.
The PHP script should be setting the Content-Type header.
if(isset($_POST['ajax']) && $_POST['ajax'] === '1') {
header('Content-Type: application/json');
echo json_encode(validateForm($_POST));
}

How can I use JSONP to download client-side javascript objects?

I'm trying to get client-side javascript objects saved as a file locally. I'm not sure if this is possible.
The basic architecture is this:
Ping an external API to get back a JSON object
Work client-side with that object, and eventually have a "download me" link
This link sends the data to my server, which processes it and sends it back with a mime type application/json, which (should) prompt the user to download the file locally.
Right now here are my pieces:
Server Side Code
<?php
$data = array('zero', 'one', 'two', 'testing the encoding');
$json = json_encode($data);
//$json = json_encode($_GET['']); //eventually I'll encode their data, but I'm testing
header("Content-type: application/json");
header('Content-Disposition: attachment; filename="backup.json"');
echo $_GET['callback'] . ' (' . $json . ');';
?>
Relevant Client Side Code
$("#download").click(function(){
var json = JSON.stringify(collection); //serializes their object
$.ajax({
type: "GET",
url: "http://www.myURL.com/api.php?callback=?", //this is the above script
dataType: "jsonp",
contentType: 'jsonp',
data: json,
success: function(data){
console.log( "Data Received: " + data[3] );
}
});
return false;
});
Right now when I visit the api.php site with Firefox, it prompts a download of download.json and that results in this text file, as expected:
(["zero","one","two","testing the encoding"]);
And when I click #download to run the AJAX call, it logs in Firebug
Data Received: testing the encoding
which is almost what I'd expect. I'm receiving the JSON string and serializing it, which is great. I'm missing two things:
The Actual Questions
What do I need to do to get the same prompt-to-download behavior that I get when I visit the page in a browser
(much simpler) How do I access, server-side, the json object being sent to the server to serialize it? I don't know what index it is in the GET array (silly, I know, but I've tried almost everything)
You need to tell the browser to visit the page, usually by setting window.location.
Since it's a string, it will be sent as part of the raw query string. Try looking in $_SERVER['QUERY_STRING'] for it.

Categories