Get Progress of PHP Script using jQuery.ajax - php

I am using jQuery's ajax to run a php script with the below:
jQuery.ajax({
type: "POST",
url: "my_php_script.php",
success: function( response ) {
console.log(response);
},
error: function(){
console.log('error is...');
}
});
my_php_script.php loops through an array and on each product runs a function:
$count = count($array);
$i = 0;
foreach ($array as $item) {
myFunction($item);
$i++;
if($i == $count){
echo json_encode('all done and a success');
}
}
This all works but the script can generally take around 2-3 minutes to finish so I need to show the progress for the viewer whilst it runs. How can i do this?
I can get the percent of the loop by adding
$percent = intval($i/$count * 100)."%";
echo json_encode($percent);
into my php loop as so:
$count = count($array);
$i = 0;
foreach ($array as $item) {
myFunction($item);
$percent = intval($i/$count * 100)."%";
echo json_encode($percent);
$i++;
if($i == $count){
echo json_encode('all done and a success');
}
}
But how can i get this value in my jQuery ajax call?

$.ajax({
url: path,
xhrFields: {
onprogress: function (e) {
}
},
success: function (response) {
}
});
Found this example hope it helps.

Got this working in the end by writing the percentage in a uniquely named text file as so in my array loop:
$percent = intval($i/$count * 100)."%";
$_text = file_get_contents($_file);
$_text = $percent;
file_put_contents($_file, $_text);
And then in my html page i check the contents of the file every 2 seconds by:
jQuery.get('file.txt?'+new Date(), function(data) {
console.log(data);
}, 'text');
I'm sure this isn't the best way of doing so but to get this working in a limited time period it's all i could come up with. Hope it helps anyone else

Related

how to put value on progress bar when data is huge in php/laravel?

I want to show a progress of data processed (in backend )on progress bar (on front).
For this 2 things am doing,
1] Sent one request to get session variable
interval = setInterval(function () {
$.getJSON('/importProgress', function (data) {
$('#putProgressPercent').html(data['progressPercent'] + "%");
$('#putProgressPercentMessage').html(data['progressMessage'] );
$("#progressBarLine").css("width", data['progressPercent'] + "%");
if (data['progressPercent'] == 100) {
clearInterval(interval);
$("#loaderModal").hide(); // hide div
}
});
}, 1000);
Initially will get 0, but when other (below) request is processing will get percentage
2] Send other request for data submission on backend side (in my case with for loop) like below
$.ajax({
headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')},
url: "/storeData",
type: "post",
data: {
'someValue': someVaribaleToProcress,
},
success: function (response) {
var returnDetails = jQuery.parseJSON(response);
if (returnDetails['error']) {
alert(returnDetails['error']);
return false;
}
},
error: function (jqXHR, textStatus, errorThrown) {
clearInterval(interval);
}
});
and on back side this processes as below :
$chunksData = array_chunk($myData,3);
foreach ($chunksData as $index => $oneChunkData) {
foreach ($oneChunkData as $oneIndex => $details) {
$isImported = ImportData::addImportData($variables_1, $variables_2);
}
$parsedChunk += sizeof($oneChunkData);
$completedPercent = (round(($parsedChunk * 100) / sizeof($getTempTableData)));
echo $completedPercent. " : is percent <br>";
session()->put('importProgress', $completedPercent);
session()->save();
}
}
This $myData is huge. (suppose 1k now).
Now the problem is until this above for loop (of putting data in db) is completed, the interval hits are in pending state. so not getting updated with data.
even above line of printing percentage (echo $completedPercent. " : is percent";) is also not printing output until all data is processed.
can someone give me solution for this?

My ajax taking too much time in for loop calling a php file

My Ajax is taking too much time on loading am calling ajax from 1 to 3000
It hit on database and get if value exist in database from 1 to 3000 then it will return
Here's my code
function Getdata(e) {
e = e;
jQuery.ajax({
type: "GET",
async: true,
url: "getdata.php",
data: "id=" + e,
success: function(t) {
jQuery(".reult_get_wish-" + e).html(t.htmltext)
},
dataType: "json"
})
}
for (var e = 1; e <= 3000; e++) {
Getdata(e);
}
Here's my getdata.php file code
$id = $_GET['id'];
$sql = "SELECT * from wishing_report where user = '".$id."'";
$result = $mysqli->query($sql);
if ($e = $result->fetch_array(MYSQLI_ASSOC))
{
echo json_encode($e);
}
Explained
If it takes some time, why not use an asynchronous approach, where you can process 'x' amount at a time, i.e. you could use setTimeout and recursion or setInterval, just so you can process a block of information/data at a time.
In this example you can see that there's an onIterate function and a onComplete function, both of these are used in different scenarios, you can use the onIterate function for each iteration, prior to the iterate function being complete. Once you've iterated enough, this is when you can fire the onComplete function, feel free to make any changes you like, i.e. include promises or whatever takes your fancy.
This could also be a better approach for the server as you're allowing the server time to recover from the last request. Alternatively you could alter your back end code so that it's more efficient, etc, you could use some limit and offset parameter(s) within your query to ensure the server isn't handling too much data at one time.
// A function to fire when the ajax request has finished.
const onSuccess = data => {
console.log(data);
};
// Simulate the ajax request.
const getData = (i, callback) => {
setTimeout(() => {
console.log(i);
return callback(i);
}, 500);
}
// A function to fire once complete.
const onComplete = () => console.log('Finished');
// A function to fire if it's not finished/complete.
const onIterate = () => console.log('NOT finished yet');
// A function to iterate, break the loop up into chuncks.
const iterate = (start, end, delay) => {
const process = data => {
iterate(++start, end, delay)
if (start > end) {
onComplete(data);
} else {
onIterate(data);
}
};
if (start <= end) {
setTimeout(() => {
getData(start, process);
}, delay);
}
};
// A starting point.
const start = () => iterate(0, 10, 1500);
// Just start the function.
start();
Your Ajax is taking a lot of time beacause you're running it 3000 times. To avoid calling it many times, I recommend putting all ids in array. I would do something like this.
JavaScript:
function Getdata(e) {
e = e;
jQuery.ajax({
type: "POST",
async: true,
url: "getdata.php",
data: {id: e},
success: function(t) {
$.each(t, function() {
$.each(this, function(k, v) {
jQuery(".reult_get_wish-" + v).html(v.htmltext);
});
});
},
dataType: "json"
})
}
var arr = [];
for (var e = 1; e <= 3000; e++) {
arr.push(e);
}
Getdata(arr);
PHP:
$id = $_POST['id'];
$sql = "SELECT * from wishing_report where user IN ('".implode(',', $id)."')";
$result = $mysqli->query($sql);
if ($e = $result->fetch_array(MYSQLI_ASSOC))
{
echo json_encode($e);
}

Trying to populate worker ID using Compay Name but only the first worker in that company is displayed in dropdown

This is the view page code in code Igniter.
I am able to populated the second drop down(worker Id) but the problem is, only first data is being fetched. As it has more than 50 worker, only 1 worker id is being fetched.
$(document).ready(function() {
$('#name_of').change(function() {
var Worker_id = $('#name_of').val();
$.ajax({
type:'POST',
data:{data:Worker_id},
dataType:'text',
url:"<?php echo base_url(); ?>supply_chain/get_filtered_names_for_time_card",
success:function(result) {
result = JSON.parse(result);
$('#Worker').empty();
for(i in result) {
$('#Worker').append("<option value='"+result[i]['Worker_id']+"'>"+result[i]['Worker_id']+" "+result[i]['Worker_name']+"</option>")
}
}
});
});
});
This is the Controller function for above View through which I am trying to get all workers related to that required company name.
public function get_filtered_names_for_time_card() {
$id = $this->input->post('data');
$companyName = $this->supply_model->get_all_names_for_time_card();
for($i = 0;$i < sizeof($companyName);$i++){
if($companyName[$i]['company_name'] == $id){
$data['companyNameOptions'] = [$companyName[$i]];
break;
}
}
echo json_encode($data['companyNameOptions']);
}
It would be a much better idea to make the query select only the row you want but your problem with the code you have written is you over writing the data each time round your loop
Also once you find a company_name you want you terminate the for loop with a break so you will only ever add one to the resulting $data array
public function get_filtered_names_for_time_card()
{
$id = $this->input->post('data');
$companyName = $this->supply_model->get_all_names_for_time_card();
for($i = 0;$i < sizeof($companyName);$i++){
if($companyName[$i]['company_name'] == $id){
$data['companyNameOptions'][] = $companyName[$i];
// note here ^^
//break;
}
}
echo json_encode($data['companyNameOptions']);
}
Also the $data array does not need to have a sub array so above code can be written more simply and clearly as
public function get_filtered_names_for_time_card()
{
$id = $this->input->post('data');
$companyName = $this->supply_model->get_all_names_for_time_card();
for($i = 0;$i < sizeof($companyName);$i++){
if($companyName[$i]['company_name'] == $id){
$data[] = $companyName[$i];
}
}
echo json_encode($data);
}
And in your javascript, if you are returning JSON then tell the ajax call that you are doing that and you can forget about the JSON.parse()
$(document).ready(function(){
$('#name_of').change(function(){
var Worker_id = $('#name_of').val();
$.ajax({
type:'POST',
data:{data:Worker_id},
//dataType:'text',
dataType:'json',
url:"<?php echo base_url(); ?>supply_chain/get_filtered_names_for_time_card",
success:function(result)
{
//result = JSON.parse(result);
$('#Worker').empty();
for(i in result){
$('#Worker').append("<option value='"+result[i]['Worker_id']+"'>"+result[i]['Worker_id']+" "+result[i]['Worker_name']+"</option>")
}
}
});
});
});

ajax and php to load more content from mysql when page gets to bottom

I've seen some answers to this question on this site already, but i still haven't been able to implement it as i want to for 2 days now. I'm sort of a beginner so a very clear explanation would be of great help,
i have a mysql database of some data, i want to read from a table and display 30 rows at a time, when the user scrolls to the end of the page, i want to load another 30 rows (i have been able to do the first 30, but loading the remaining is a challenge for me).
i already have this:
$(document).ready(function(){
$(window).scroll(function() {
if($(window).scrollTop() == $(document).height() -$(window).height()) {
//ive tried all sorts of things here it just doesnt work
}
});
also an example of the php file that loads the next contents would help,
i'm using php and mysqli
thanks a lot in advance.
so this is my loadmore.php, its for the functionality, haven't styled the output:
<?php
require_once 'functions.php'; //my databse connection is in this file
//i created a function queryMysql($query) in functions.php, thats what is used here
$result = queryMysql("SELECT * FROM articles WHERE live='1' ORDER BY created DESC LIMIT $start, 30");
$num = $result->num_rows;
for ($j = 0 ; $j < $num ; ++$j){
$row = $result->fetch_array(MYSQLI_ASSOC);
$title = $row['title'];
$subtitle = $row['subtitle'];
echo "$title<br />$subtitle";
}?>
for the ajax, i changed it to the first answer i got here, but all my attempts have looked like this:
$(window).scroll(function() {
if($(window).scrollTop() == $(document).height() - $(window).height()) {
$.ajax({
type: method,
data: {}, //Your data
url: 'loadmore.php',
async: true,
success: function (data, textStatus, jqXHR) {
$('#article-inro-hold').append(data);
},
error: function (jqXHR) {
//Error handler
}
});
}
});
Try to implement jquery ajax, something rough like this:
$(document).ready(function () {
$(window).scroll(function () {
if ($(window).scrollTop() == $(document).height() - $(window).height()) {
$.ajax({
type: method,
data: {}, //Your data
url: 'your/url/to/get/more/content/from',
async: true,
success: function (data, textStatus, jqXHR) {
$('#myDiv').append(data);
},
error: function (jqXHR) {
//Error handler
}
});
}
});
});
You have to make an ajax call for each time, when you scroll amount get up, nearer to document height. Along with you also have to manage your offset, otherwise you will get duplicate records (You can use hidden field for that), and pass it each time in your ajax call.
<div id="ajax-response"></div>
<input type="hidden" value="0" id="offset" />
<script>
$(document).ready(function(){
$(window).scroll(function() {
if($(window).scrollTop() == $(document).height() - $(window).height()) {
$.ajax({
url: 'requesthandler.php',
type: 'post',
data: {
task: 'show-more',
offset: document.getElementById('offset').value
},
success: function(response){
jsonObj = $.parseJSON(response);
$('#ajax-response').append(jsonObj.html);
document.getElementById('offset').value = jsonObj.offset;
}
})
}
});
});
and requesthandler.php will look like:
if($_POST['task'] == 'show-more'){
$offset = (int) $offset;
$sql = "SELECT * FROM table limit $offset, 10";
$data = '';
foreach ($conn->query($sql) as $row) {
$data .= "<div>$row['column']</div>";
}
echo json_encode(array(
'offset' => ($offset + 10),
'html' => $data,
))
}
$query = $db->query("SELECT * FROM bags ORDER BY id DESC LIMIT 7");
Can we use $_POST here to get only needed information.
$limit=($_POST["bag"]);
$query = $db->query("SELECT * FROM bags WHERE id = '.$limit.' ORDER BY id DESC LIMIT 7");

Success handling behavior in Ext.Ajax.request

I am working on extjs 4 project. In this project I have to communicate back and fourth between js and php files. So to call php from js, I am using Ext.Ajax.request.
var dirs = [];
Ext.Ajax.request(
{
url: 'text.php',
method: 'GET',
success: function(response)
{
dirs = JSON.parse(response.responseText);
},
failure: function(response)
{
alert('server-side failure with status code ' + response.status);
}
});
// Creating dropdown list menu
document.write("<select class='select'>");
for (var i = 0; i < dirs.length; i++)
{
document.write("<option>" + dirs[i] + "</option>");
}
document.write("</select>");
php code is the following:
<?php
$filepath = "scenarios";
$dirs = array();
$files = array();
$scenes = array_diff(scandir($filepath), array('..', '.'));
for ($i = 2; $i < count($scenes)+2; $i++)
{
if (strpos($scenes[$i], '.'))
{
array_push($files, $scenes[$i]);
}
else
{
array_push($dirs, $scenes[$i]);
}
}
if (count($dirs) > 0)
{
echo json_encode($dirs);
}
else
{
echo json_encode("You do nat have any projects. Please create new project.");
}
?>
Now the problem appears in the part where I want to generate list menu from the resulting dirs object. In the firebug DOM dirs = ["google","yahoo"], but in the loop, dirs.length returns 0???
Also when I put alert(dirs.length) before the for loop, it shows 0, then correctly generates the list menu...weird????
The request call is asynchronous which means, that after calling Ext.Ajax.Request, the next instruction is your loop. But you haven't received the data from the server yet. You need to put the loop in the success callback to make sure that you'll execute it after getting the data from the server.
var dirs = [];
Ext.Ajax.request(
{
url: 'text.php',
method: 'GET',
success: function(response)
{
dirs = JSON.parse(response.responseText);
// Creating dropdown list menu
document.write("<select class='select'>");
for (var i = 0; i < dirs.length; i++)
{
document.write("<option>" + dirs[i] + "</option>");
}
document.write("</select>");
},
failure: function(response)
{
alert('server-side failure with status code ' + response.status);
}
});
Also when I put alert(dirs.length) before the for loop, it shows 0,
then correctly generates the list menu...weird????
This is because the alert stop the execution flow of your program until you click on "ok". The data are probably coming from the server during this time, and the dir variable is populated with them.
I can't see any headers being sent out - which is required by most browsers:
header('content-type: application/json; charset=utf8;');
if(sizeof($dirs) > 0){
echo json_encode(array('success' => true, 'data' => $dirs));
}
else {
echo json_encode(array('success' => false, 'error' => 'You do not have any projects.' ));
}
The JavaScript:
var xhr = new Ext.data.Connection();
xhr.request({
url: '/text.php',
method: 'GET',
headers: {'Accept':'application/json'},
success: function(response, opts) {
var obj=Ext.decode(response.responseText);
var html='';
Ext.each(obj.data, function(v,i){html+='<option>'+v+'</option>';});
html='<select>'+html+'</select>';
console.info(html);
}
});
The HTML generation has to reside in the callback function - else it makes no sense at all.
Without having seen the JSON which is being returned - it's hard to tell what's wrong with it.
Down-voting without leaving a comment why exactly is really lame.

Categories