json_encode returns 200 and undefined - php

I'd like to have a code to add or remove from database bookmarks.
The code is ready and it adds and removes from database bookmarks correctly, but when I call the function it keeps returning the json error instead json success even if the code works.
I'd like to know what's wrong with the code (that I got and adapt from somewhere else) because the client side is not receiving the correct values true or false, it only triggers the json beforeSending and json error.
server side:
if($isFavorite) {
// if it's favorite, remove from bookmarks
return json_encode(array("status" => true, "added" => false));
} else {
// if it's not favorite, include into bookmarks
return json_encode(array("status" => false, "added" => true));
}
client side:
<script>
function addItemToUsersList(userId, type, itemId) {
jQuery.ajax({
'url': 'xxx',
'type': 'GET',
'dataType': 'json',
'data': {userid: userId, type: type, itemid: itemId},
'success': function(data) {
console.log('json success');
},
'beforeSend': function() {
console.log('json beforeSending');
},
'error': function(data) {
console.log('json error');
console.log(data.status + ' ' + data.added);
}
});
}
</script>
The console.log(data.status + ' ' + data.added); line logs 200 undefined
How may I return the correct values true or false for both "status" and "added"?
Edit:
The json success is never logged on console, so I don't know what happened on server side. I need to know this because I need to change the class of an element to display an empty or yellow star.

If you are returning the result and not doing anything with that return elsewhere, you will not get any response to your ajax call, so it's undefined. As #MikeC says, you must echo it at some point.
If you are not already echoing it elsewhere, try:
$response = array(
'status' => $isFavourite,
'added' => !$isFavourite
);
echo json_encode($response);
My suggestion is also if 'status' and 'added' are really just the opposite of each other every time, then you probably only need to send 'status' on its own. In your JS you can just check 'status' and reverse the boolean as I've done above, if you want to know what the value of added would be.
var added = !data.status;
Update
If your ajax request is coming back to the error function, the request itself is probably failing.
Change your error function to this, to debug what has happened:
'error': function(jqXHR, status, error) {
console.log(status);
console.log(error);
}
You might have an error in server-side code somewhere or you're calling the wrong PHP script perhaps?

Related

Ajax Call Back and Laravel

I have created an API which my AJAX post send values to it. AJAX does post and my laravel API does process the values. My issues is with the callback returning the value back to my AJAX post. My AJAX doesn't return the results in the success section when I do console log. I would like the results from my api to can use data to make my condition. At the moment, the console log doesn't even return a value. But in my chrome inspector under preview it shows the response from my API but not in the success section.
AJAX
var fname = "Joe";
var lname = "Test";
var processUrl = "api.example.com/z1";
$.ajax({
type: 'POST',
url: processUrl,
data: {"name": fname,"surname": lname},
dataType: 'json',
success: function(res){
console.log(res);
if(res.length >= 1){
$('#display').val(res.name);
}
}
});
PHP
public function checkResults(Request $request){
$name = $request->name." ".$request->surname;
$result = array();
$result['name'] = [$name];
return response()->json($result,201);
}
For first it will be good to return with 200 OK response code (instead of 201).
Note: If you want to just immediately get the answer for your question only, you can see the last part of this answer (usage of "done/fail" construct instead of "success/error").
Additional:
There is many patterns which are used by Client(Frontend)<->API<->Server(Backend) developers.
Approximately all APIs built without any 500 server error codes. But there is exists also many differences between APIs structures.
One of them is to send response like this (this is the only one example of response):
return response()->json([
'success' => true, // true or false
'message' => "Message about success!",
], 200); // 200, 401, 403, 404, 409, etc
The other approach is to always sending 200 OK, but message can be also about error:
return response()->json([
'success' => false, // true or false
'code' => 404,
'message' => "Resource not found!",
], 200);
This kind of methods will written under try{}catch() and will return only 200, but that messages can imitated also as an error (as in example).
The other (appropriate approach for you) is to change your Frontend AJAX functionality like this:
$.ajax({
type: 'POST',
url: processUrl,
data: {
{{--_token: "{{ csrf_token() }}",--}}
name: fname,
surname: lname
},
dataType: 'json'
}).done(function(res) {
console.log(res);
if(res.length >= 1) {
$('#display').val(res.name);
}
}).fail(function(jqXHR, textStatus, errorThrown) {
console.log("Error: " + textStatus);
});
AJAX .done() function replaces method .success() which was deprecated in jQuery 1.8. This is an alternative construct for the success callback function (like before: "success: function(){...}").
AJAX .fail() function replaces method .error() which was deprecated in jQuery 1.8. This is an alternative construct for the complete callback function (like before: "error: function(){...}").
Note: .error() callback is called on HTTP errors, but also if JSON parsing on the response fails. This is what's probably happening if response code is 200/201 but you still are thrown to error callback.
I believe this is happening because you are sending status code 201 (Created), but you need to send status code 200 (OK) to trigger the success callback.
public function checkResults(Request $request){
$name = $request->name." ".$request->surname;
$result = array();
$result['name'] = [$name];
return response()->json($result,200);
}
I couldn't find it specifically in the jQuery docs, but this SO question addresses it.
Due to the asynchronous nature of Ajax calls, do not put them in the normal execution flow of your program. See this post to get more insight.
A quick fix for your problem is to include the ajax call in a function and call that function anytime you want to interact with the server asynchronously.
var fname = "Joe";
var lname = "Test";
var processUrl = "api.example.com/z1";
ajaxCall();
function ajaxCall() {
$.ajax({
type: 'POST',
url: processUrl,
data: {"name": fname,"surname": lname},
dataType: 'json',
success: function(res){
console.log(res);
if(res.length >= 1){
$('#display').val(res.name);
}
},
error: function() {
console.log('error');
}
});
}
In addition, include an error function in the ajax call settings to handle cases where the ajax request fails. See this answer for alternative styles of doing this.

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')
});

Throw exception, but json response get status SUCCESS

I have this part of code in Controller, but when i make this action and IF works fine and the error message appears in console log.
But it looks like 'success' has status true. And it shouldn't
Try {
if ($last['date']) {
if ($last['date']->format('d-m-Y') == $par['date']) {
throw new \Exception('error', 500);
}
}
return new JsonResponse([
'success' => true,
'data' => $content,
'message' => 'success'
]);
} catch (\Exception $exception) {
return new JsonResponse([
'success' => false,
'code' => $exception->getCode(),
'message' => $exception->getMessage(),
]);
}
JQuery
$.ajax({
type: "POST",
url: "/app/url",
data: TableData,
dataType: "json",
success: function(response){
console.log(response.message);
$('#message').html('<p class="alert alert-success">' + response.message + '</p>');
},
error: function (response) {
console.log(response.message);
$('#message').html('<p class="alert alert-danger">' + response.message + '</p>');
}
});
Your AJAX code is receiving the response as success every time, regardless of the JSON content, because you're always sending a 200 response (which is success). To tell AJAX to process the response as an error (and go to the error method instead of success method in your AJAX response handler), you need to send an error code in the response, i.e. 400, like this:
return new JsonResponse([
'success' => false,
'code' => 400,
'message' => $exception->getMessage(),
], 400);
So, if you're throwing your custom Exceptions, you need to set the code property for each according to their real HTTP meaning.
Now, the success and error handlers in AJAX have different parameters. In success, the first parameter is data, simply the data returned from the server. On the other hand, in error, the first parameter is an jqXHR object. To access the data in this object, you have a handful of different parameters, but what you need now, since you have JSON, is jqXHR.responseJSON. So, now your error message will be in response.responseJSON.message, not in response.message. See more about this here.

JSONP Ajax Error Jquery(Number String) Not Called

Since moving my site to https, the mailchimp api no longer works with the standard json ajax calls. These calls now render a same origin policy error. I don't know why this is the case though, because I'm calling a url on my own server. After some investigating, I've surmised that JSONP is my only option. The following script posts correctly to mailchimp but Im unable to get a successful response.
$.ajax({
type:"GET",
url:"https://mysite/book_subscription_process.php?jsonp=?",
data:{fname: $('#fNBookId').val(), lname: $('#lNBookId').val(), email: $('#eBookId').val()},//only input
dataType: "jsonp",
cache: false,
async: false,
jsonp: false,
success: function(data){
console.log('success');
if(data.message == 'failure')
{
alert('Error','There was an error processing your subscription. Please try again.');
}else if(data.message == 'success')
{
alert('success');
}else{
console.log(data.message);
}
},
error: function (xhr, ajaxOptions, thrownError, data) {
// console.log(data.message);
console.log('failure');
alert(xhr.status);
alert(thrownError);
}
});
Server side:
<?php
header("content-type: text/javascript");
if(isset($_GET['jsonp']))
{
$obj->fname = $_GET['fname'];
$obj->lname = $_GET['lname'];
$obj->email = $_GET['email'];
$obj->success = 'success';
$obj->failure = 'failure';
}
header("Content-type: application/json");
$MailChimp = new \Drewm\MailChimp($api_key);
$book = array('id' => $group_id, 'groups' => array('Book'));
$merge_vars = array('FNAME'=> $obj->fname,
'LNAME'=>$obj->lname,
'GROUPINGS'=>array($book)
);
$result = $MailChimp->call('lists/subscribe', array(
'id' => $list_id,
'email' => array('email'=>$obj->email),
'merge_vars' => $merge_vars,
'double_optin' => false,
'update_existing' => true,
'replace_interests' => false,
'send_welcome' => false,
));
if ( ! empty( $result['leid'] ) ) {
echo json_encode($obj->success);
}
else{
echo json_encode($obj->failure);
}
?>
As I said above the info is correctly posted to mailchimp. Each time however, the ajax call errors. I get a 200 OK but get a Jquery[bunch of numbers] not called. The json_encode success statement is executed on the server. Is there a special way that I'm supposed to handle the server side response? Or am I supposed to do something differently on the client side? Thanks in advance.
Same Origin means that the page making the request and the destination server need to have identical protocol, server, and port. For this particular situation, MailChimp isn't either of those -- the page making the request is your HTML page and the server is https://mysite/book_subscription_process.php.
Since you said this corresponds to your move to HTTPS, my guess is that you've moved one end but not the other. Since the code above looks like the front-end page is calling https://mysite, I'd triple check to make sure that the HTML and all scripts are also being served from https://mysite.
I don't think you should need JSONP in this scenario -- it sounds like you are attempting to work from the same origin, you just need to be sure you're doing that properly.

ajax always runs success even when error is returned

I have an AJAX script that should insert data into a mysql database when users are logged in. However it is currently running the success function, even when 'success' => 'false' is returned in the console.
Her is my code
$(document).ready(function() {
$("#addfav").click(function() {
var form_data = {heading: $("#vidheading").text(), embed : $("#vidembed").text()};
jQuery.ajax({
type:"POST",
url:"http://localhost/stumble/Site/add_to_fav",
dataType: "json",
data: form_data,
success: function (data){
alert("This Video Has Been Added To Your Favourites");
console.log(data.status);
},
error: function (data){
if(data.success == false){
alert("You Must Be Logged In to Do That");
console.log(data.status);
};
}
});
})
})
here is the php, bear in mind my project is in codeigniter.
public function add_to_fav(){
header('Content-Type: application/json');
$this->load->model('model_users');
$this->model_users->add_favs();
}
and this is the actual model for adding data to db
public function add_favs(){
if($this->session->userdata('username')){
$data = array(
'username' => $this->session->userdata('username'),
'title' => $this->input->post('heading'),
'embed' => $this->input->post('embed')
);
$query = $this->db->insert('fav_videos',$data);
echo json_encode(array('success'=>'true'));
} else {
echo json_encode(array('success'=>'false'));
}
}
Thank you for any suggestions!
You aren't returning an error.
You are returning a 200 OK with the data {"success": "false"}.
You can either handle that in your jQuery success function or send a different status code (it looks like a 403 error would fit here).
You have to remember error that occurs for asynchronous requests and errors that occur for PHP backend are different. Your error occurs at PHP-level, and PHP returns valid HTML as far as the javascript frontend is concerned. You need to check if the "success" variable in the returned JSON is true.

Categories