Unwanted "data" wrapper in PHP response to AngularJS query - php

I am querying some server with AngularJS using $http.get
var onStuff = function(data) {
console.log( "Stuff received: " + angular.toJson(data));
$scope.stuff = data.data;
};
$http.get("https://some.server.net/stuff")
.then(onStuff, onError);
My back end is written in php and returns a properly formatted JSON.
I checked that loading https://some.server.net/stuff in a browser and testing by command line "php stuff.php" . It looks something like (truncated with ... to fit this screen):
[{"id":"1","user_id":"1","name":"Name1"},
{"id":"2","user_id":"1","name":"Name2"},
...
]
Please note this data is "unwrapped" or "just the array"
However, when onStuff() is invoked my array is "wrapped" inside another data object
Here is the console output
Stuff received:
{"data":[{"id":"1","user_id":"1","name":"Name1"},
{"id":"2","user_id":"1","name":"Name2"},...],
"status":200,
"config":{"method":"GET",
"transformRequest":[null],
"transformResponse":[null],
"url":"https://some.server.net/stuff",
"headers":{"Accept":"application/json, text/plain, */*"}},
"statusText":"OK"}
Here is the php stuff
<?
header('content-type: application/json; charset=utf-8');
header("access-control-allow-origin: *");
require_once("stuff.class.php");
$mysqli = new mysqli( "localhost", "user", "password", "database");
$list = Stuff::getList( $mysqli);
echo json_encode( $list);
$mysqli->close();
?>
I have been following a tutorial using github api, the JSON response was available directly in data
I am pretty sure this has to do with HTTP headers, but I hoped content-type would take care of it
What should I do to remove the unwanted "data" wrapper?

Instead of using the generic promise API (which seems to return an object with everything inside), use the success and error methods provided by $http:
var onStuff = function(data) {
console.log( "Stuff received: " + angular.toJson(data));
$scope.stuff = data.data;
};
$http.get("https://some.server.net/stuff")
.success(onStuff).error(onError);
That should gives you the data in the format you expect. The full API is as follow:
$http({method: 'GET', url: '/someUrl'}).
success(function(data, status, headers, config) {
// this callback will be called asynchronously
// when the response is available
}).
error(function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});

It seems like you expect onStuff to receive only the deserialized JSON data, but that's not what the API does. The object passed to your $http.get(...).then() callback (i.e. onStuff) is a response object with five properties: data, status, headers, config, and statusText--which is exactly what you're seeing in your console output. The data property has the deserialized JSON data, which is why you have to do $scope.stuff = data.data.
If you want onStuff to receive only the deserialized JSON data, you'll have to call it through an intermediary:
$http.get("https://example.com/stuff")
.then( function(response) {
onStuff(response.data);
} );

Related

Passing via GET json to ajax jquery,

I'm getting from a php page a json after a json encode. I correctly see the json in page that i want to pass to ajax. The data i send are taken via get from a form in php, saved in an array and then passsed with json encode.
But i get the error object from ajax:
What i'm missing? Should i copy and paste part of my backend too?
$.ajax({
method: "GET",
url: "queries/queries.php",
dataType: "json",
succes: function(data){
console.log(data);
console.log('json found');
},
error: function(error){
console.log(error);
console.log('json not found');
}
});
backend:
$calls= "text";
for ($i=0;$i<count($array);$i++) {
$schemaTab = $array[$i] . $calls;
$query = "SELECT * from 'schema'.'table'"; // this is just a sample query
$res=$db->getQuery($query); // this is a function that output the db query
header('Content-Type: application/json');
echo json_encode($res); // the json i pass
}
json:
[{"Schema":"schemaName1","DATEHOUR":"10\/05\/2021 11:56","count":"4"}]
[{"Schema":"schemaName2","DATEHOUR":"10\/05\/2021 10:21","count":"3"}]
[{"Schema":"schemaName3","DATEHOUR":null,"count":"0"}]
[{"Schema":"schemaName4","DATEHOUR":null,"count":"0"}]
Your JSON is invalid. JSON must consist of one thing such an a string, object, or array. (Objects and arrays can nest as many other things as they like inside them).
You have an array ([{"Schema":"schemaName1","DATEHOUR":"10\/05\/2021 11:56","count":"4"}]) which would be valid JSON but then you have another array and so on.
Gather up all your data into a variable in your PHP.
Then have header('Content-Type: application/json'); echo json_encode($that_variable) once, outside the loop.

angular-php: form data is empty in php

I am using angular as frontend and php as backend here is the code of angular.
$scope.processForm = function($scope.formData) {
console.log($scope.formData);
$http({
method : 'POST',
url : 'process.php',
data : {'data': $scope.formData,'uid':uid}, // no need to use $.param, even never see it in angular
headers : { 'Content-Type': 'application/x-www-form-urlencoded' }
})
here is the process.php
$postContent= file_get_contents("php://input");
$req= json_decode($postContent);
$formData= $req->formData;
$uid= $req->uid;
problem is $formData is empty in php. however $uid is showing value.
in form i have two entry email and password but i don't know how can i use that in php because formdata is empty.
I checked in firebug and found data is posting.
{"formData":{"password":"ff","cpassword":"errgreg"},"uid":"75"}:""
But nothing is coming response tab of firebug.
Assuming you call your function with something like ng-submit="processForm(formData)" then this is all you actually need
$scope.processForm = function(formData) {
$http.post('process.php', {
formData: formData, // note the key is "formData", not "data"
uid: uid // no idea where uid comes from
});
};
Where you have
$scope.processForm = function($scope.formData) {
isn't even valid JavaScript. You cannot use object dot notation in function argument names. That should have been throwing an error in your console.
You also appeared to be incorrectly setting your request content-type. You are sending JSON, not application/x-www-form-urlencoded formatted data. Angular's default POST content-type (application/json) is sufficient.
Try like this..
$json='{"formData":{"password":"ff","cpassword":"errgreg"},"uid":"75"}';
$req= json_decode($json);
$formData= $req->formData;
$uid= $req->uid;
$password = $req->formData->password;
$cpassword = $req->formData->cpassword;
OR convert into array using json_decode() with second argument as true.
$json='{"formData":{"password":"ff","cpassword":"errgreg"},"uid":"75"}';
$req= json_decode($json,true);//converts into array format
$formData= $req['formData'];
//print_r($formData);
echo $formData['password'];

AJAX request to PHP - Handling response data

Im working on some AJAX login function, making a request via PHP.
I am wondering how do I return data via the PHP so that I can handle it like the code mentioned below. I only worked on the javascript side and not the PHP server side so I am confused now.
I want to get a value/values stored in the response like data.name , data.sessionID , data.listOfnames
Is the data a JSON Object by itself?
Thanks!
The code below was used before and has been verified to work.
function retrieveVersion(){
var URL = RSlink + "/updates";
$.ajax({
headers : {
"Content-Type" : "application/json; charset=UTF-8",
"sessionid" : result
},
type : "GET",
url : vURL,
statusCode : {
0 : function() {
hideLoadingMsg();
showError(networkError, false);
},
200 : function(data) {
currentVersion = String(data.version);
updatesArray=data.updates;
});
}
}
});​
Suppose you have a php file for handling ajax calls. It should be available by this url - vURL.
In this file you need to create an array.
Something like this:
$data = array('data' => array('version' => yourversion, 'updates' => yourupdates));
Then you need to convert this object into json string. You can do this using json_encode() function
echo json_encode($data);
One thing to keep in mind: You need to echo your data and only. If somewhere in your file you will have some other echo-es, the result string returning to your ajax-funtion might be broken.

$http headers is not a function - angularjs

I am posting data to Dynamics CRM via SOAP on my PHP server with cURL. After this is done it is giving the entity GUID in the form of a HTTP Response header. When attempting to access this via my angular factory and $http.
My header is exposed and is able to be viewed in Chrome Developer tools and gives me the GUID I need.
The code for accessing the promise data is as follows:
$http({
method: 'POST',
url: url,
data: formData,
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).success(function (data, headers) {
var array = [];
array.data = data;
array.headers = headers('EntityId');
console.log(array.headers);
deferred.resolve(array);
})
return deferred.promise;
//etc
The error I get is:
headers is not a function()
I can however, access some header result such as a status 200 code by using:
array.headers = headers;
But I need to access my custom header. Any ideas on how I can achieve this?
As per Deprecation Notice on https://docs.angularjs.org/api/ng/service/$http
The $http legacy promise methods success and error have been
deprecated. Use the standard then method instead. If
$httpProvider.useLegacyPromiseExtensions is set to false then these
methods will throw $http/legacy error.
the preferred way would be:
$http.get('/someUrl')
.then(function(response){
var array = [];
array.data = response.data;
array.headers = response.headers('EntityId');
});
As Andy said already, headers is the 3rd parameter of the success callback. So you will have to do this:-
success(function(data, status, headers, config) {
// this callback will be called asynchronously
// when the response is available
})
I wasn't going to add this as an answer but doing this as I wanted to add that headers is indeed a function.
In my project, I did the below and saw function logged out as type in console. The function returns the value of the header item corresponding to the name passed, if no parameters are passed, returns an object containing all headers.
login(user) {
return this.$http.post(this.url, user)
.success((data, status, headers, config) => {
console.log(typeof headers, 'headers'); => prints function
console.log(headers(), 'headers'); => if you don't pass anything, returns an object containing all headers.
return response;
});
}
Excerpt from the angular code.
function headersGetter(headers) {
var headersObj;
return function(name) {
if (!headersObj) headersObj = parseHeaders(headers);
if (name) {
var value = headersObj[lowercase(name)];
if (value === void 0) {
value = null;
}
return value;
}
return headersObj;
};
You parameters for success are incorrect. headers is the third parameter.
$http.get('/someUrl').
success(function(data, status, headers, config) {
// this callback will be called asynchronously
// when the response is available
}).
error(function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
Check "Usage" section in https://docs.angularjs.org/api/ng/service/$http for reference.
The $http service is a function which takes a single argument — a configuration object — that is used to generate an HTTP request and returns a promise.
The response object has these properties:
data – {string|Object} – The response body transformed with the transform functions.
status – {number} – HTTP status code of the response.
headers –{function([headerName])} – Header getter function.
config – {Object} – The configuration object that was used to generate the request.
statusText – {string} – HTTP status text of the response.
Angular version == 1.3.5 , Suppose header value has been set "X-AUTH-TOKEN = 'eyJwYXNzd29yZCI6ImFkbWlu'" in Application Security class after authentication.
$scope.postData = "{\"username\" : username , \"password\": password ,\"email\" :email}";
$http({
method: 'POST',
url: '/API/authenticate',
data: postData,
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"X-Login-Ajax-call": 'true'
}
})
.then(function(response) {
if (response.data == 'ok') {
$cookies['X-AUTH-TOKEN']=response.headers('X-AUTH-TOKEN');
// below put,put,putObject Cookies value is valid for Angular version >= 1.4
// $cookies.putObject('X-AUTH-TOKEN',response.headers('X-AUTH-TOKEN');
window.location.replace('/');
}
else {
// Error Message...
}
});

Getting json on Ajax response callback

I am trying to create a little ajax chat system (just for the heck of it) and I am using prototype.js to handle the ajax part.
One thing I have read in the help is that if you return json data, the callback function will fill that json data in the second parameter.
So in my php file that gets called I have:
header('Content-type: application/json');
if (($response = $acs_ajch_sql->postmsg($acs_ajch_msg,$acs_ajch_username,$acs_ajch_channel,$acs_ajch_ts_client)) === true)
echo json_encode(array('lastid' => $acs_ajch_sql->msgid));
else
echo json_encode(array('error' => $response));
On the ajax request I have:
onSuccess: function (response,json) {
alert(response.responseText);
alert(json);
}
The alert of the response.responseText gives me {"lastid": 8 } but the json gives me null.
Anyone know how I can make this work?
This is the correct syntax for retrieving JSON with Prototype
onSuccess: function(response){
var json = response.responseText.evalJSON();
}
There is a property of Response: Response.responseJSON which is filled with a JSON objects only if the backend returns Content-Type: application/json, i.e. if you do something like this in your backend code:
$this->output->set_content_type('application/json');
$this->output->set_output(json_encode($answer));
//this is within a Codeigniter controller
in this case Response.responseJSON != undefined which you can check on the receiving end, in your onSuccess(t) handler:
onSuccess:function(t) {
if (t.responseJSON != undefined)
{
// backend sent some JSON content (maybe with error messages?)
}
else
{
// backend sent some text/html, let's say content for my target DIV
}
}
I am not really answering the question about the second parameter of the handler, but if it does exist, for sure Prototype will only provide it in case of proper content type of the response.
This comes from Prototype official :
Evaluating a JavaScript response
Sometimes the application is designed
to send JavaScript code as a response.
If the content type of the response
matches the MIME type of JavaScript
then this is true and Prototype will
automatically eval() returned code.
You don't need to handle the response
explicitly if you don't need to.
Alternatively, if the response holds a
X-JSON header, its content will be
parsed, saved as an object and sent to
the callbacks as the second argument:
new Ajax.Request('/some_url', {
method:'get', onSuccess:
function(transport, json){
alert(json ? Object.inspect(json) : "no JSON object");
}
});
Use this functionality when you want to fetch non-trivial
data with Ajax but want to avoid the
overhead of parsing XML responses.
JSON is much faster (and lighter) than
XML.
You could also just skip the framework. Here's a cross-browser compatible way to do ajax, used in a comments widget:
//fetches comments from the server
CommentWidget.prototype.getComments = function() {
var commentURL = this.getCommentsURL + this.obj.type + '/' + this.obj.id;
this.asyncRequest('GET', commentURL, null);
}
//initiates an XHR request
CommentWidget.prototype.asyncRequest = function(method, uri, form) {
var o = createXhrObject()
if(!o) { return null; }
o.open(method, uri, true);
o.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
var self = this;
o.onreadystatechange = function () {self.callback(o)};
if (form) {
o.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
o.send(makePostData(form));
} else {
o.send('');
}
}
//after a comment is posted, this rewrites the comments on the page
CommentWidget.prototype.callback = function(o) {
if (o.readyState != 4) { return }
//turns the JSON string into a JavaScript object.
var response_obj = eval('(' + o.responseText + ')');
this.comments = response_obj.comments;
this.refresh()
}
I open-sourced this code here http://www.trailbehind.com/comment_widget

Categories