Need help formulating a correct JSON response - php

I am a novice using Jquery ajax calls and json responses and have hit a bump that I need help to overcome.
I am using cleeng open API and I am wondering about the response from one of the api calls I am using – getRentalOffer().
I am using jquery $ajax() request and I want to make the getRentalOffer() api call and return the result in JSON format. My efforts so far is this (assume a POST request with id as parameter.)
Request:
<script type="text/javascript">
$(document).ready(function() {
$( "#getOfferButton" ).click(function() {
var offerId = document.frm.offerID.value;
$.ajax({
// the URL for the request
url: "ajax-get-offer.php",
// the data to send (will be converted to a query string)
data: {
id: offerId
},
// whether this is a POST or GET request
type: "POST",
// the type of data we expect back
dataType : "json",
// code to run if the request succeeds;
// the response is passed to the function
success: function(json) {
// $("#title").val = json.title;
/*
$.each(json, function(i, item){
$("#"+item.field).val(item.value);
});
*/
console.log(json);
},
// code to run if the request fails; the raw request and
// status codes are passed to the function
error: function( xhr, status, errorThrown ) {
alert( "Sorry, there was a problem!" );
console.log( "Error: " + errorThrown );
console.log( "Status: " + status );
console.dir( xhr );
},
// code to run regardless of success or failure
complete: function( xhr, status ) {
alert( "The request is complete!" );
}
});
});
});
</script>
ajax-get-offer.php:
<?php
include_once('Cleeng-cleeng-php-sdk-fe2a543/cleeng_api.php');
/*
Using FirePHP to log variables
*/
require_once('FirePHPCore/FirePHP.class.php');
ob_start();
$firephp = FirePHP::getInstance(true);
$offerID = $_POST['id'];
$firephp->log($offerID, 'offerID');//For debugging
$publisherToken = 'My super secret token goes here!';
$cleengApi = new Cleeng_Api();
$cleengApi->setPublisherToken($publisherToken);
$offerDetails = $cleengApi->getRentalOffer($offerID);
$firephp->log($offerDetails, 'offerDetails');//For debugging
echo $offerDetails;
?>
When I try this I get Internal server error. I tried to use echo json_encode($offerDetails); on that last echo statement and then I do not get the server error. However the response only seem to contain the last element of the JSON object.
I need help to understand what I need to do with the API response from getRentalOffer() in order to pass it as a proper JSON response to the $ajax() request.
I hope my question make sense. :-)
Edit: Using print_r insead of echo I do get a response text but sadly with an error. This is the text and it looks to me as if it need to be formatted correctly before using print_r.
"Cleeng_Entity_RentalOffer Object ( [id:protected] => R875937249_SE [publisherEmail:protected] => martin.xxxxxxxx#xxxxxxx.se [url:protected] => http://xxx.xxxxxx.xx/cleeng_tool [title:protected] => Tjohooo! [description:protected] => En skön rulle om Afrika. [price:protected] => 55 [applicableTaxRate:protected] => 0.21 [period:protected] => 48 [currency:protected] => EUR [socialCommissionRate:protected] => 0 [contentType:protected] => video [contentExternalId:protected] => xxxxxxxxxxx [contentExternalData:protected] => {"platform":"vimeo","dimWidth":"500","dimHeight":"369","hasPreview":false,"previewVideoId":"","backgroundImage":"https://i.vimeocdn.com/video/xxxxxxxxx_960.jpg"} [contentAgeRestriction:protected] => [tags:protected] => Array ( [0] => abo ) [active:protected] => 1 [createdAt:protected] => 1400588711 [updatedAt:protected] => 1400606512 [pending:protected] => [averageRating] => 4 ) "

You cannot echo arrays or object, try using
print_r($offerDetails);
or
var_dump($offerDetails);

Solved.
The object returned by getRentalOffer() contains protected members which will not be encoded by json_encode because it respects the access parameters in the object vars. I found a nice solution in this post: http://smorgasbork.com/component/content/article/34-web/65-json-encoding-private-class-members
It is not a robust solution as it relies on a loophole that one day might be shut so beware of that. But for my needs it will suffice.

Related

my ajax call is getting correct response but isn't doing anything

I'm trying to make a like/dislike button in ajax. The ajax is sending my data to a separate file where it is saved in a database and that file sends back the successful response {"status":"success","message":"Like has been saved.","data":{"like":"1"}} that I got from the chrome network response window. However the code in $ajax(...).done isn't working
I have console.logged and var.dumped every bit of code i possibly could. my data IS being sent to my database which should mean that the SQL and the like class is correct. I've also tried simply console.log 'ging the response "res" and putting the rest in comments, but that again gives me nothing
<div>
Like
Dislike
<span class='likes' data-id="<?php echo $post->id ?>"><?php echo $post->getLikes(); ?></span> people like this
</div>
$("a.like, a.dislike").on("click",function(e){
var postId = $(this).data("id");
if($("a.like")){
var type = 1;
}else if($("a.dislike")){
var type = 0;
}
var elLikes = $(this).siblings(".likes");
var likes=elLikes.html();
$.ajax({
method: "POST",
url: "ajax/postlike.php",
data: {postId: postId, type:type},
dataType: "json",
})
.done(function( res ) {
console.log(res);
if(res.status=="succes"){
console.log(res);
if(res.data.like=="1"){
likes++;
elLikes=html(likes);
$("a.like").css("display","none");
$("a.dislike").css("display","inline-block");
} else if(res.data.like=="0"){
likes--;
elLikes=html(likes);
$("a.dislike").css("display","none");
$("a.like").css("display","inline-block");
}
}
});
e.preventDefault();
});
if(!empty($_POST)){
try {
$postId=$_POST['postId'];
$type=htmlspecialchars($_POST['type']);
$userId=$_SESSION['user_id'];
$l = new Like();
$l->setPostId($postId);
$l->setUserId($userId);
$l->setType($type);
$l->save();
$res = [
"status" => "success",
"message" => "Like has been saved.",
"data" =>[
"like" => $type
]
];
}catch (trowable $t) {
$res = [
'status' => 'failed',
'message' => $t->getMessage()
];
}
echo json_encode($res);
var_dump($res);
}
what I expected to happen was that Ajax sent the JSON data to the php code, that put it in a database, which works. Then gives a successful response to the Ajax, also works. The Ajax would then switch out the like/dislike buttons whilst adding or taking 1 like from the span "likes". It however does absolutely nothing
I'm almost 100% certain that the problem is something stupid that I'm overlooking, but i really can't find it.
Typo in 'success' in on line: if(res.status=="succes"){
you can try with this:
error: function(xhr, status, error) {
console.log(error)
},
success: function(response) {
console.log(response)
}
in your Ajax function, to know what happen in the server side with the response.
If you specify a return data type for the ajax request to expect, and the actual returned value isn't what you specified, then your error/fail function will be triggered if you have one. This is because adding dataType: "json" causes you're ajax try and parse your return value as json and when it fails, it triggers your error handler. It's best to omit the dataTaype and then add a try catch with JSON.parse in your done function, to get around this.
E.G
.done(function (string_res) {
console.log(string_res);
try {
var json_obj = JSON.parse(string_res);
console.log(json_obj);
} catch (e) {
console.log('failed to parse');
}
// do work/operations with json_obj not string_res
})
.fail(function (jqXHR, textStatus) {
console.log('failed')
});

SugarCRM: How to get json data in REST endpoint

I have added an extra action to the recordlist view;
custom/modules/Opportunities/clients/base/views/recordlist/recordlist.js:
({
extendsFrom: 'RecordlistView',
initialize: function(options) {
this._super("initialize", [options]);
//add listener for custom button
this.context.on('list:opportunitiesexport2:fire', this.export2, this);
},
export2: function() {
//gets an array of ids of all selected opportunities
var selected = this.context.get("mass_collection").pluck('id');
if (selected) {
return App.api.call('read',
App.api.buildURL('Opportunities/Export2'),
{'selected_ids':selected},
{
success: function(response) {
console.log("SUCCESS");
console.log(response);
},
error: function(response) {
console.log('ERROR');
console.log(response);
},
complete: function(response){
console.log("COMPLETE");
console.log(response);
},
error: function(response){
console.log("ERROR");
console.log(response);
}
});
}
},
})
The tutorial here
http://support.sugarcrm.com/Documentation/Sugar_Developer/Sugar_Developer_Guide_7.7/Integration/Web_Services/v10/Extending_Endpoints/
Explains how to create an endpoint.
However it doesn't explain how to get the json data (the stringified array of selected ids);
custom/modules/Opportunities/clients/base/api/OpportunitiesApi.php:
class OpportunitiesApi extends SugarApi
{
public function registerApiRest()
{
return array(
//GET
'MyGetEndpoint' => array(
//request type
'reqType' => 'GET',
//set authentication
'noLoginRequired' => false,
//endpoint path
'path' => array('Opportunities', 'Export2'),
//endpoint variables
'pathVars' => array('', ''),
//method to call
'method' => 'Export2',
//short help string to be displayed in the help documentation
'shortHelp' => 'Export',
//long help to be displayed in the help documentation
'longHelp' => 'custom/clients/base/api/help/MyEndPoint_MyGetEndPoint_help.html',
),
);
}
/**
* Method to be used for my MyEndpoint/GetExample endpoint
*/
public function Export2($api, $args)
{
//how to access $args['selected_ids']?
}
}
$args contains
Array
(
[__sugar_url] => v10/Opportunities/Export2
)
Is it possible to access the json data?
I did the same but my rest api was coded in java. I used java #Path annotation to annotate my get method. I then deployed above rest api code to a server(Tomcat in my case). Starting the server and then hitting the URL formed by the #Path will give you the json data on the browser.
The solution was to change the call method to create and the endpoint method to POST; $args now contains
Array
(
[selected_ids] => Array
(
[0] => 0124a524-accc-11e6-96a8-005056897bc3
)
[__sugar_url] => v10/Opportunities/Export2
)
PUT vs POST in REST - I was using GET because I didn't plan to change anything, but the body is typically ignored in a GET request.

$http.post from angular reaches php, but response is not received back in angularjs

I'm having this weird issue where you already did something thousands of time but this time won't work. I've been on it for two days and can't fix it.
So my code is very simple :
js :
$http.post('datas/test.php', data)
.success(function(response)
console.log(response);
})
.error(function() {
console.log("error");
});
test.php :
<?php
$user=json_decode(file_get_contents('php://input'));
echo json_encode($user);
?>
When I do a console.log(data) before the $http.post it's containing an object with two fields which are both strings but the console.log(response) give me a null so every time I try to access a variable like $user->something it gives me an error.
I'm having a second issue that is really weird too : when I run my app and call the $http.post it gives me all the errors I said before, but if I try an other time, the $http.post won't call at all until I reboot the server (it's giving me a bad gateway).
I tested many things like changing the way I call my file :
$http({
method: 'POST',
url: 'datas/test.php',
data: data,
headers: {'Content-Type': 'application/x-www-form-urlencoded'} // Or 'application/json'
});
but this is giving me exactly the same behavior.
Thank you in advance for helping me out and have a good day ! ;)
PS: I'm using PHPStorm in case it has anything to do with the server reboot thing.
If you use the content type 'application/x-www-form-urlencoded' you should pass the data in the urlencoded format (ie. "var1=val1&var2=val2").
Otherwise, if you use 'application/json', you can pass directly your javascript object.
Let me know if I can help you better.
Bye
For First Approach
To use angular $http.post in correct way you shoud handal promise correctly by using .then method not the success method.
$http.post('/someUrl', data, config).then(successCallback, errorCallback);
Please check the angular documentation for using $http.post
For Second Approach
Look like data is not transform correctly. By default, the $http service will transform the outgoing request by serializing the data as JSON and then posting it with the content-type, "application/json". But you want to post the value as a FORM post, so you need to change the serialization algorithm and post the data with the content-type, "application/x-www-form-urlencoded".
Following code reference from this link
var request = $http({
method: "post",
url: "datas/test.php",
transformRequest: transformRequestAsFormPost,
data: {
id: 4,
name: "Test",
status: "Something"
}
});
// Store the data-dump of the FORM scope.
request.success(
function( html ) {
$scope.cfdump = html;
}
);
And the TransformRequestAsFormPost implementation
app.factory(
"transformRequestAsFormPost",
function() {
// I prepare the request data for the form post.
function transformRequest( data, getHeaders ) {
var headers = getHeaders();
headers[ "Content-type" ] = "application/x-www-form-urlencoded; charset=utf-8";
return( serializeData( data ) );
}
// Return the factory value.
return( transformRequest );
// ---
// PRVIATE METHODS.
// ---
// I serialize the given Object into a key-value pair string. This
// method expects an object and will default to the toString() method.
// --
// NOTE: This is an atered version of the jQuery.param() method which
// will serialize a data collection for Form posting.
// --
// https://github.com/jquery/jquery/blob/master/src/serialize.js#L45
function serializeData( data ) {
// If this is not an object, defer to native stringification.
if ( ! angular.isObject( data ) ) {
return( ( data == null ) ? "" : data.toString() );
}
var buffer = [];
// Serialize each key in the object.
for ( var name in data ) {
if ( ! data.hasOwnProperty( name ) ) {
continue;
}
var value = data[ name ];
buffer.push(
encodeURIComponent( name ) +
"=" +
encodeURIComponent( ( value == null ) ? "" : value )
);
}
// Serialize the buffer and clean it up for transportation.
var source = buffer
.join( "&" )
.replace( /%20/g, "+" )
;
return( source );
}
}
);
The problem I had here came from a FileReader I opened earlier in my JS :
reader.readAsBinaryString($scope.file);
reader.onload = function (e) {
//stuff
};
the readAsBinaryString function made the file_get_contents("php://input") unable to work correctly.
Once replaced with
reader.readAsDataURL($scope.file);
every thing worked fine.
Thanks to Giulio for helping me to troubleshoot this.

jQuery ajax returning unexpected data type

attempting to implement some server side error checking for input in the very useful "handsontable" jscript library.
the following call works great:
jQuery.ajax({
url: "index.php?option=com_catalogscontroller=batchsave",
data: {"formData": querydata.getData().splice( 0, 1 ) },
dataType: 'JSON',
type: 'POST',
success: function ( response ) {
if( response.success ) {
} else {
querydata.loadData( response.data );
}
}
});
I thought the most effective way to do error checking is on the server (PHP) side, to create a multidimensional array to track any errors discovered by the server and then return that array with the form data in the same ajax call. So I modified the server code to return both the form data and the error array back to the javascript ajax call. i.e.:
if( !empty( $errors ) ) // $errors is an multi dimensional array same size as the form data
$result['success'] = false;
$result['msg'] = 'There were errors detected';
$result['data']['form'] = $formData;
$result['data']['errors'] = $errors;
}
echo json_encode( $result );
and then on the client side, the javascript routine above has been modified to:
jQuery.ajax({
url: "index.php?option=com_catalogscontroller=batchsave",
data: {"formData": querydata.getData().splice( 0, 1 ) },
dataType: 'JSON',
type: 'POST',
success: function ( response ) {
if( response.success ) {
} else {
formErrors = response.data.errors; // formErrors is a global
querydata.loadData( response.data.form );
}
}
});
The original function of the form is preserved (the form data is retrieved and properly inserted in the html), but formErrors returns with a result to me that is baffling. An alert immediately after the assignment 'alert( formErrors )' shows something like a list:
true,true,false,true,true
and I can also alert on a specific index without problem e.g. alert( formErrors[0][2] ); would display 'false'. But outside of the ajax call, the array seems to be inaccessible, giving 'undefined' errors. And both in the ajax call, and in routines outside of the ajax call alert( typeof formErrors ) displays 'object' and alert( formErrors) gives the same comma list as above, but I don't want an object, I am expecting an array OR i'd be happy with an object as long as i could access it by indices. What am I missing here?
The problem I was having appear to be centered around JSONing.
Most docs identify the requirement to JSON variables in php routines supporting a Javascript AJAX call. The use of the jQuery.ajax call alleviates some of the requirement, but if you don't know what you're doing (like me), its easy to get in trouble.
My php routine JSON encodes the complete response record with the statement:
return json_encode( $result );
Because of my:
dataType: JSON
parameter in the jQuery.ajax() call, this results in an automatic json.parse() of the result returned by the PHP routine to the jQuery javascript function. This is not successful however because the php json_encode call in the server code is not recursive, so while the result array is decoded, any arrays within that result are not.
the solution then is to json encode the components of the multidimensional array and then decode them on the client side. e.g.
if( !empty( $errors ) )
$result['success'] = false;
$result['msg'] = 'There were errors detected';
$result['data']['form'] = json_encode( $formData );
$result['data']['errors'] = json_encode( $errors );
}
echo json_encode( $result );
And then on the client side, parse (decode) these arrays specifically:
jQuery.ajax({
url: "index.php?option=com_catalogscontroller=batchsave",
data: {"formData": querydata.getData().splice( 0, 1 ) },
dataType: 'JSON',
type: 'POST',
success: function ( response ) {
if( response.success ) {
} else {
formErrors = JSON.parse( response.data.errors ); // formErrors is a global
querydata.loadData( JSON.parse( response.data.form ) );
}
}
});
I confess freely that I don't really know what I'm doing, but the code structured above seems to make sense for the logic I've developed to explain it AND it is working for me.
Anyway, thanks again to Nathan and pdoherty926.

How can I access my PHP variables when calling ajax in jQuery?

I am attempting to create a simple comment reply to posts on a forum using the AJAX function in jQuery. The code is as follows:
$.ajax({type:"POST", url:"./pages/submit.php", data:"comment="+ textarea +"& thread="+ currentId, cache:false, timeout:10000,
success: function(msg) {
// Request has been successfully submitted
alert("Success " + msg);
},
error: function(msg) {
// An error occurred, do something about it
alert("Failed " + msg);
},
complete: function() {
// We're all done so do any cleaning up - turn off spinner animation etc.
// alert("Complete");
}
});
Inside the submit.php file I have this simple if->then:
if(System::$LoggedIn == true)
{
echo "Yes";
} else {
echo "No";
}
This call works on all other pages I use on the site, but I cannot access any of my variables via the AJAX function. I've tested everything more than once and I can echo back whatever, but anytime I try to access my other PHP variables or functions I just get this error:
Failed [object XMLHttpRequest]
Why am I unable to access my other functions/variables? I must submit the data sent into a database inside submit.php using my already made $mySQL variable, for example. Again these functions/variables can be accessed anywhere else except when I call it using this AJAX function. After hours of Googling I'm just spent. Can anyone shed some light on this for me? Many thanks.
The PHP script that you have only returns a single variable. Write another script that that returns JSON or if you are feeling brave XML. below is a quick example using JSON.
In your javascript
$.ajax({
type: 'GET'
,url: '../pages/my_vars.php'
,dataType: 'json'
,success: function(data){
// or console.log(data) if you have FireBug
alert(data.foo);
}
});
Then in the php script.
// make an array or stdClass
$array = array(
'foo' => 'I am a php variable'
,'bar' => '... So am I'
);
// Encodes the array into JSON
echo json_encode($array);
First thing, you have a space in the Data Parameter String for the URL - will cause problems.
Secondly, your success and error functions are referencing a variable msg. It seems you are expecting that variable to be a string. So, the question then becomes - What is the format of the output your PHP script at submit.php is producing?
A quick read of the jQuery API suggests that, if the format of the response is just text, the content should be accessible using the .responseText property of the response. This is also inline with the response you say you are getting which states "Failed [object XMLHttpRequest]" (as you are trying to turn an XHR into a String when using it in an alert.
Try this:
$.ajax( {
type: "POST" ,
url: "./pages/submit.php" ,
data: "comment="+ textarea +"&thread="+ currentId ,
cache: false ,
timeout: 10000 ,
success: function( msg ) {
// Request has been successfully submitted
alert( "Success " + msg.responseText );
} ,
error: function( msg ) {
// An error occurred, do something about it
alert( "Failed " + msg.responseText );
} ,
complete: function() {
// We're all done so do any cleaning up - turn off spinner animation etc.
// alert( "Complete" );
}
} );

Categories