Continuously get PHP loop data in Ajax Call - php

I have this codes in process.php:
$users = $_POST['users']; // Sample: "user1, user2, user5"
$users = explode(', ', $users);
$step = 0;
foreach ($users as $r) {
$user_email = get_user_email($r); // Get email of each user
if (!empty($user_email)) {
send_w_mail(); // Send email to each user
$step++;
echo json_encode(
['step' => $step, 'all' => count($users)]
); // echo output
}
}
And this is my ajax call in index.php:
$("#send-message").click(function () {
$.ajax({
url: global_base_url + 'process.php', // global_base_url defined.
async : true,
type: 'POST',
data: {'users': input_users}, // input_users is val() of a input.
encoding: 'UTF-8',
success: function (data) {
data = $.trim(data);
if (data){
data = $.parseJSON(data);
var p_value = parseInt(data.step*100)/data.all;
set_progressbar_value(p_value); // set progressbar value. sample: 23%
}
}
});
});
This codes don't have any problem for execute and showing result.
But I want to Continuously get output json data from process.php in order to show process of each $step in Percent unit in a bootstrap process-bar;
I found some function like ignore_user_abort(), ob_clean() and ob_flush() but don't know how can I solve my problem with them.
How Can I do this? Please help me to solve the problem.
Thanks a lot.

There are two ways of approaching this problem
Websocket
Long polling
I will be describing the long polling method here:
$users = $_POST['users']; // Sample: "user1, user2, user5"
$users = explode(', ', $users);
$step = 0;
foreach ($users as $r) {
$user_email = get_user_email($r); // Get email of each user
if (!empty($user_email)) {
send_w_mail(); // Send email to each user
$step++;
echo json_encode(
['step' => $step, 'all' => count($users)]
); // echo output
//Flush the output to browser
flush();
ob_flush();
}
Jquery does not provide api for XMLHttpRequest.readyState == 3 (Loading docs here) so we need to use raw XMLHttpRequest object
$("#send-message").click(function () {
var prev_response = "";
var xhr = new XMLHttpRequest();
xhr.open("POST", global_base_url + 'process.php', true);
//Send the proper header information along with the request
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = function() {//Call a function when the state changes.
if(xhr.readyState == 3) {
// Partial content loaded. remove the previous response
var partial_response = xhr.responseText.replace(prev_response,"");
prev_response = xhr.responseText;
//parse the data and do your stuff
var data = $.parseJSON(partial_response);
var p_value = parseInt(data.step*100)/data.all;
set_progressbar_value(p_value);
}
else if(xhr.readyState == 4 && xhr.status == 200){
set_progressbar_value(100);
console.log("Completed");
}
}
xhr.send("users="+ input_users);
});

Related

Ajax never initiating success: when using xhrFields

I am having trouble getting the success call to fire in my ajax request. I know the communication is working fine, but the last call in my PHP script, which is a return json_encode($array); will fire as if it is a part of the onprogress object. I would like to "break" the onprogress call and run the success function on the last data sent via return json_encode when the PHP script has terminated...
Here is my AJAX call:
$( document ).ready(function(e) {
var jsonResponse = '', lastResponseLen = false;
$("#btn_search").click(function(e){
var firstname = document.getElementById('firstname').value;
var lastname = document.getElementById('lastname').value;
$.ajax({
type: "POST",
url: 'search.php',
data: $('#search_fields').serialize(),
dataType: "json",
xhrFields: {
onprogress: function(e) {
var thisResponse, response = e.currentTarget.response;
if(lastResponseLen === false) {
thisResponse = response;
lastResponseLen = response.length;
} else {
thisResponse = response.substring(lastResponseLen);
lastResponseLen = response.length;
}
jsonResponse = JSON.parse(thisResponse);
document.getElementById('progress').innerHTML = 'Progress: '+jsonResponse.msg;
}
},
success: function(data) {
console.log('done!');
document.getElementById('progress').innerHTML = 'Complete!';
document.getElementById('results').innerHTML = data;
}
});
e.preventDefault();
});
});
And here is the basic PHP server script:
<?php
function progress_msg($progress, $message){
echo json_encode(array('progress' => $progress, 'msg' => $message));
flush();
ob_flush();
}
$array = array('msg' => 'hello world');
$count = 0;
while($count < 100){
progress_message($count, "working....");
$count += 10;
sleep(2);
}
return json_encode($array);
?>
I made your code work, there were 2 errors. First, in your while loop, your function name is incorrect, try this:
progress_msg($count, "working... ." . $count . "%");
Secondly, the very last line outputs nothing, so technically you don't get a "successful" json return. Change the last line of your server script from:
return json_encode($array);
to:
echo json_encode($array);
UPDATE: Full working code with hacky solution:
Ajax:
$( document ).ready(function(e) {
var jsonResponse = '', lastResponseLen = false;
$("#btn_search").click(function(e){
var firstname = document.getElementById('firstname').value;
var lastname = document.getElementById('lastname').value;
$.ajax({
type: "POST",
url: 'search.php',
data: $('#search_fields').serialize(),
xhrFields: {
onprogress: function(e) {
var thisResponse, response = e.currentTarget.response;
if(lastResponseLen === false) {
thisResponse = response;
lastResponseLen = response.length;
} else {
thisResponse = response.substring(lastResponseLen);
lastResponseLen = response.length;
}
jsonResponse = JSON.parse(thisResponse);
document.getElementById('progress').innerHTML = 'Progress: '+jsonResponse.msg;
}
},
success: function(data) {
console.log('done!');
dataObjects = data.split("{");
finalResult = "{" + dataObjects[dataObjects.length - 1];
jsonResponse = JSON.parse(finalResult);
document.getElementById('progress').innerHTML = 'Complete!';
document.getElementById('results').innerHTML = jsonResponse.msg;
}
});
e.preventDefault();
});
Search.php:
<?php
function progress_msg($progress, $message){
echo json_encode(array('progress' => $progress, 'msg' => $message));
flush();
ob_flush();
}
$array = array('msg' => 'hello world');
$count = 0;
while($count <= 100){
progress_msg($count, "working... " . $count . "%");
$count += 10;
sleep(1);
}
ob_flush();
flush();
ob_end_clean();
echo json_encode($array);
?>
The problem with the "success" method of the ajax call was that it couldn't interpret the returning data as JSON, since the full return was:
{"progress":0,"msg":"working... 0%"}{"progress":10,"msg":"working... 10%"}{"progress":20,"msg":"working... 20%"}{"progress":30,"msg":"working... 30%"}{"progress":40,"msg":"working... 40%"}{"progress":50,"msg":"working... 50%"}{"progress":60,"msg":"working... 60%"}{"progress":70,"msg":"working... 70%"}{"progress":80,"msg":"working... 80%"}{"progress":90,"msg":"working... 90%"}{"progress":100,"msg":"working... 100%"}{"msg":"hello world"}
Which is not a valid JSON object, but multipje JSON objects one after another.
I tried removing all previous output with ob_end_clean(); , but for some reason I can't figure out, it didn't work on my setup. So instead, the hacky solution I came up with was to not treat the return as JSON (by removing the dataType parameter from the AJAX call), and simply split out the final Json element with string operations...
There has got to be a simpler solution to this, but without the use of a third party jQuery library for XHR and Ajax, I couldn't find any.

XHR and php Progress bar, working on local, not on remote

More explanation here :
Im importing products to my DB, and everytime a product is imported I display the percent calculated earlier:
//Progress bar
set_time_limit(0);
ob_implicit_flush(true);
ob_end_flush();
sleep(1);
$p = ($i/$count_product)*100; //Progress
$response = array( 'success' => true , 'message' => $p . '% ','progress' => $p);
$i++;
echo json_encode($response);
On my local everything is working fine :
Every time php echo json_encode() I get on XHR a new state 3, and display the response.
Code below:
var xhr = new XMLHttpRequest();
xhr.previous_text = '';
$param = 'id='+$(this).find('input').val();
xhr.onerror = function() {console.log(xhr.responseText) };
xhr.onreadystatechange = function() {
//try{
console.log(xhr.readyState);
console.log(xhr);
console.log(new_response);
if (xhr.readyState == 4){
var new_response = xhr.responseText.substring(xhr.previous_text.length);
var result = JSON.parse( new_response );
if (result['message'] == '100' ) {
$('.progress_bar').html('<div><?=$this->translate->_("Imported succefully")?></div>');
$.when($('.full_screen_layer').fadeOut(2000)).done(function() {
location.reload();
});
}else{
$('.progress_bar').html('<div style="color:red">'+result['message']+'</div>');
setTimeout(function(){
$.when($('.full_screen_layer').fadeOut(2000)).done(function() {
location.reload();
});
}, 2000);
// alert('<?=$this->translate->_("Please try again")?>');
}
}
else if (xhr.readyState > 2){
var new_response = xhr.responseText.substring(xhr.previous_text.length);
var result = JSON.parse( new_response );
if (result['success'] && result['end'] == undefined) {
$('.progress_bar').html('<div>'+result['message']+'</div>');
xhr.previous_text = xhr.responseText;
}else{
$('.progress_bar').html('<div style="color:red">'+result['message']+'</div>');
}
}
//}
// catch (e){
// alert("[XHR STATECHANGE] Exception: " + e);
// }
};
xhr.open("POST", action, true);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.send($param);
But I'm trying to understand why it's not working on the server ( XHR state 3 is fired only once, at the end of the request ( so the json is malformed )
Here are the headers:
This just break my mind, if someone have an idea, even a bad one xD
(Btw there is a proxy on the server : VIA:1.1 Alproxy ) it could stop the response untill it end and then send it alltogether ?

Why do the responses of my new plugin not save?

So below are some of the actions that my plugin is supposed to perform when submitting the survey. On my console I should get 'response saved', but I get absolutely nothing, not even 'Could not save response'. I have looked through the code, but I can't see why ajax is not performing the function of saving the response. Can anyone else see what is going on here?
// 5.3
// hint: ajax form handler for saving question responses expects: $_POST['survey_id'] and $_POST['response_id']
function ssp_ajax_save_response() {
$result = array(
'status'=>0,
'message'=>'Could not save response.',
'survey_complete'=>false
);
try {
$survey_id = (isset($_POST['survey_id'])) ? (int)$_POST['survey_id']: 0;
$response_id = (isset($_POST['response_id'])) ? (int)$_POST['response_id']: 0;
$saved = ssp_save_response($survey_id, $response_id);
if($saved) {
$survey = get_post($survey_id);
if(isset($survey->post_type) && $survey->post_type = 'ssp_survey') {
$complete = true;
$html = ssp_get_question_html($survey_id);
$result = array(
'status'=>1,
'message'=>'Response saved!',
'survey_complete'=>$complete,
'html'=>$html
);
} else {
$result['message'].='Invalid survey.';
}
}
} catch(Exception $e) {
// php error
}
ssp_return_json($result);
}
// 5.4
// hint: saves single question response
function ssp_save_response($survey_id, $response_id) {
global $wpdb;
$return_value = false;
try {
$ip_address = ssp_get_client_ip();
// get question post object
$survey = get_post($survey_id);
if($survey->post_type == 'ssp_survey'):
// get current timestamp
$now = new DateTime();
$its = $now->format('Y-m-d H:i:s');
// query sql
$sql = "INSERT INTO {$wpdb->prefix}ssp_survey_responses (ip_address, survey_id, response_id, created_at) VALUES (%s, %d, %d, %s) ON DUPLICATE KEY UPDATE survey_id = %d";
// prepare query
$sql = $wpdb->prepare($sql, $ip_address, $survey_id, $response_id, $ts, $survey_id);
// run query
$entry_id = $wpdb->query($sql);
// If response saved successfully...
if($entry_id):
// return true
$return_value = true;
endif;
endif;
} catch(Exception $e) {
// php error
ssp_debug('ssp_save_response php error', $e->getMessage());
}
return $return_value;
}
Someone made me aware that I need to add the jQuery code and so here it is and thank you in advance.
jQuery(document).ready(function($){
// do something after jQuery has loaded
ssp_debug('public js script loaded!');
// hint: displays a message and data in the console debugger
function ssp_debug(msg, data) {
try {
console.log(msg);
if(typeof data !== "undefined") {
console.log(data);
}
} catch(e) {
}
}
// setup our wp ajax URL
var wpajax_url = document.location.protocol + '//' + document.location.host + '/wp-admin/admin-ajax.php';
// bind custom function to survey form submit event
$(document).on('submit', 'ssp-survey-form', function(e){
// prevent form from submitting normally
e.preventDefault();
$form = $(this);
$survey = $form.closest('.ssp-survey');
// get selected radio button
$selected = $('input[name^="ssp_question_"]:checked', $form);
// split field name into array
var name_arr = $selected.attr('name').split('_');
// get the survey id from the last item in name array
var survey_id = name_arr[2];
// get the response id from the value of the selected item
var response_id = $selected.val();
var data = {
_wpnonce: $('[name="wp_nonce"]', $form).val(),
_wp_http_referer: $('[name="wp_http_referer"]', $form).val(),
survey_id: survey_id,
response_id: response_id
};
ssp_debug('data', data);
// get the closest dl.ssp-question element
$dl = $selected.closest('dl.ssp-question');
// submit the chosen item via ajax
$.ajax({
cache: false,
method: 'post',
url: wpajax_url + '?action=ssp_ajax_save_response',
dataType: 'json',
data: data,
success: function(response) {
// return response in console for debugging...
ssp_debug(response);
// If submission was successful...
if(response.status) {
// update the html of the current li
$dl.replaceWith(response.html);
// hide survey content message
$('.ssp-survey-footer', $survey).hide();
} else {
// If submission was unsuccessful...
// notify user
alert(response.message);
}
},
error: function(jqXHR, textStatus, errorThrown) {
// output error information for debugging...
ssp_debug('error', jqXHR);
ssp_debug('textStatus', textStatus);
ssp_debug('errorThrown', errorThrown);
}
});
});
});

Ajax response return undefined

Hi I have been using ajax for many times. But I can't figure out whats the problem with my code this time. My head is blowing up since 2 days. I am using pusher for the realtime notification in CodeIgniter. Here's my code.
$(document).on("click", ".myonoffswitch", function () {
if (confirm("Sure!!! You want to Change the post status?"))
{
var thiss = $(this);
var prod_id = $(this).attr('id');
var status = $(this).attr('value');
var tdid = $(this).parent().prev().attr('class');
var td = $(this).parent().prev();
var adsstatus = $.ajax({type: "POST", dataType: "json", url: base_url + 'init/ads_status', data: {'prod_id': prod_id, 'status': status}});
$.when(adsstatus).done(function (adsstatuss) {
var msg;
msg = adsstatuss;
alert(msg.length);
var updated_status = msg[0].post_status;
alert(updated_status);
//alert(updated_status);
if (updated_status == "0" && tdid == prod_id) {
td.css("background", "#ccffcc");
td.text("On");
thiss.val(updated_status);
}
if (updated_status == "1" && tdid == prod_id) {
td.css("background", "#ffcccc");
td.text("Off");
thiss.val(updated_status);
}
});
}
});
ads_status (method in CodeIgniter)
public function ads_status() {
$prod_id = $_POST['prod_id'];
$status = $_POST['status'];
if ($status == "1") {
$new_status = "0";
$this->cmsdbmodel->ads_status($prod_id, $new_status);
$dat = $this->cmsdbmodel->get_updated_status($prod_id);
$ads_type = "product";
$emailreturn = $this->send_email_ads_status($prod_id, $ads_type);
//send user alert of product//
if ($dat[0]->post_status == "0") {
$lastInsertedId = $prod_id;
$modelNBrandId = $this->dbmodel->checkProductContainsAlert($lastInsertedId);
$getAlertEmail = $this->dbmodel->getAlertEmailFromBrandNModelId($modelNBrandId);
if (!empty($getAlertEmail)) {
foreach ($getAlertEmail as $alerts) {
$alertsEmail = $alerts->email;
}
}
$alertsPost = $this->dbmodel->getPostAlerts($lastInsertedId);
$sendPostAlerts = json_encode($alertsPost);
$encrytpEmail = hash('sha256', $alertsEmail);
$this->pusher->trigger($encrytpEmail, 'alerts', $sendPostAlerts);
}
//send user alert of product//
$realtime = $this->realTime_charts();
$realtime["post_status"] = $dat[0]->post_status;
$realtime["emailres"] = $emailreturn;
$data = $realtime;
$this->pusher->trigger('recent_activity', 'new_event1', $data);
echo json_encode($data);
}
}
Here I want to trigger event in pusher as well as echo json object. But in ajax, response is undefined. Also in console I can see json but when alerting the reponse it says undefined. Wheres problem in my code. Please help me.

Ajax call doesn't work from iPhone app and arduino

I've created an Arduino project wich sends the coordinates to an URL. The URL does some ajax calls. In the browser it works fine, but when I'm trying it with the Arduino it doesn't work. So I tried to do the same thing with an iOS app, but I got the same problem. This is the code on the page that the Arduino and iOS app request.
var directionsService = new google.maps.DirectionsService();
var base_url = window.location;
var received_data = <?php echo json_encode($received_data); ?>;
$.ajax({
url: 'http://gps-tracker.domain.nl/_api/handler.php',
data: { action: 'post', device_id: received_data['device_id']},
type: 'GET',
dataType:"jsonp",
jsonp:"callback",
success: function (response){
var error = [];
var total = response.length;
for (var type in response) {
if(response[type].types == 'area'){
var x = checkInsideCircle(response[type].longitude, response[type].latitude, received_data['longitude'], received_data['latitude'], response[type].reach / 1000);
if(x == false){
// Outside
error.push(true);
}else{
// Inside
error.push(false);
}
}else if(response[type].types == 'route'){
// Check route
checkOnRoute(response[type].start_latitude, response[type].start_longitude, response[type].end_latitude, response[type].end_longitude, response[type].type, response[type]['reach'], type, function(result) {
error.push(result);
if(error.length == total){
if(error.indexOf(false) >= 0){
// Device is inside route or area
outside = false;
}else{
// Send data to database
$.ajax({
url: 'http://gps-tracker.domain.nl/_api/handler.php',
data: { action: 'post', device_id: received_data['device_id'], longitude: received_data['longitude'], latitude: received_data['latitude']},
type: 'GET',
dataType: 'json',
success: function (response){
console.log('good');
},error: function(jq,status,message) {
alert('A jQuery error has occurred. Status: ' + status + ' - Message: ' + message);
}
});
}
}
});
}
}
},error: function(jq,status,message) {
alert('A jQuery error has occurred. Status: ' + status + ' - Message: ' + message);
}
});
Here is the code from the handler.php file, that the ajax request requests.
$action = isset($_REQUEST['action']) ? $_REQUEST['action'] : false;
// Switch actions
switch($action) {
case 'get':
$callback ='callback';
if(isset($_GET['callback'])){
$callback = $_GET['callback'];
}
$routes = ORM::for_table('gps_tracker_route')
->inner_join('gps_tracker_device', array('gps_tracker_device.device_id', '=', 'gps_tracker_route.device_id'))
->where('gps_tracker_route.device_id', $_GET['device_id'])
->where('gps_tracker_device.device_id', $_GET['device_id']);
if($routes = $routes->find_many()){
foreach($routes as $k=>$v){
$v = $v->as_array();
if($v['status'] == 'on' or strtotime(date('Y-m-d H:i:s')) > strtotime($v['start_time']) and strtotime(date('Y-m-d H:i:s')) < strtotime($v['end_time'])){
$response1[$k] = $v;
$response1[$k]['types'] = 'route';
}
}
}
$area = ORM::for_table('gps_tracker_area')
->inner_join('gps_tracker_device', array('gps_tracker_device.device_id', '=', 'gps_tracker_area.device_id'))
->where('gps_tracker_area.device_id', $_GET['device_id'])
->where('gps_tracker_device.device_id', $_GET['device_id']);
if($area = $area->find_many()){
foreach($area as $k=>$v){
$v = $v->as_array();
if($v['status'] == 'on' or strtotime(date('Y-m-d H:i:s')) > strtotime($v['start_time']) and strtotime(date('Y-m-d H:i:s')) < strtotime($v['end_time'])){
$response2[$k] = $v;
$response2[$k]['types'] = 'area';
}
}
}
if(isset($response1) and isset($response2)){
$response = array_merge($response1, $response2);
}elseif(isset($response1)){
$response = $response1;
}else{
$response = $response2;
}
if ( isset($response) ) {
if ( is_array($response) ) {
if (function_exists('json_encode')) {
header('Content-Type: application/json');
echo $callback.'(' . json_encode($response) . ')';
} else {
include( ABSOLUTE_PATH . '/classes/json.class.php');
$json = new Services_JSON();
echo $json->encode($response);
}
} else {
echo $response;
}
exit(0);
}else{
exit();
}
break;
case 'post':
$_GET['timestamp'] = date("Y-m-d H:i:s");
$record = ORM::for_table('gps_tracker_device_logging')->create($_GET);
$record->save();
$item = ORM::for_table('gps_tracker_device_logging')
->where('id', $record->id);
if($item = $item->find_one()){
$item = $item->as_array();
echo json_encode($item);
}
break;
default:
die('invalid call');
}
Can someone help me?
EDIT
I think it is something with Javascript. I don't know if it's possible to use javascript when a device, like Arduino, makes a http request to a server. Someone know?
I think that it's because you need a Web Browser that supports JavaScript.
I don't work with Arduino, but from what I know it does not have a "real" Web Browser - it can only pull/download data but can't execute the JS part.
For JS to work you need something to run it. That is why it works in a the browser.

Categories