I have this while loop, that basically loops through a lot of records in a database, and inserts the data in another:
$q = $con1->query($users1) or die(print_r($con2->errorInfo(),1));
while($row = $q->fetch(PDO::FETCH_ASSOC)){
$q = $con2->prepare($users2);
$q->execute(array($row['id'], $row['username'])) or die(print_r($con2-errorInfo(),1));
}
(The script has been shortened for easy reading - the correct one has a much longer array)
I would like to do this more graphical, and show a progress bar on how far it has went, instead of just seeing a page loading for a few minutes (there are ~20.000 rows in this one - I have tables with much more data)
I get that you could get the total number from the old database, and I could also easily put the current number into a variable like this:
$q = $con1->query($users1) or die(print_r($con2->errorInfo(),1));
$i = 0;
while($row = $q->fetch(PDO::FETCH_ASSOC)){
$q = $con2->prepare($users2);
$q->execute(array($row['id'], $row['username'])) or die(print_r($con2-errorInfo(),1));
$i++;
}
But now I need to actually fetch $i and display it - or something like it.
How is this "easily" done?
The code for the progress bar can either be in the same document as the while loop, or in another if easier.
You can do a "master" file that does an ajax to this first file to run a single query. You could get all the entry id's in this master file, and then pass it as a parameter to the second file that does a single query. Store these ids in a javascript array.
Create a function that does this, and when the first ajax is done, move to the second element of the id array, and do another ajax with a second parameter. That's how magento imports are done by the way :)
If you need further explanations, let me know, I tried my best to explain, but may have not been perfectly clear.
// you generate this javascript array using php.
// let's say you have all the ids that have to be processed in $Ids php array.
Ids = [<?php echo implode(',', $Ids); ?>];
function doAjax(i) {
$.ajax({ // using jquery for simplicity
'url': "ajax.php?id=" + Ids[i],
}).done(function(){
if ( i >= 0 ) {
// at the point you know you're at ((Ids.length-i)/(Ids.length) * 100) percent of the script
// so you can do something like this:
// $('.progressbar').css('width', ((Ids.length-i)/(Ids.length) * 100) + '%');
doAjax(i-1);
}
});
}
doAjax(Ids.length); // starting from the last entry
So, just to explain what this does. It starts by declaring a global javascript array that has all the ids that will need to be changed.
Then I declare a recursive ajax function, this way we can make sure that only one ajax runs at any single time (so the server doesn't blow up), and we can have a fairly accurate progress. This ajax function does the following:
Sends a request to ajax.php?id=xxx - where xxx is one of the ids in the javascript array.
In the file, we get the id ($_GET['id']), you take it from the old database, and insert it in the new one. This is only for one entry.
when the ajax is done, it goes to the done() function. Since we start the doAjax() function with the last element, we do the next iteration doAjax(i-1). Since we're going backwards in the array, we check if the key is positive. If it's not, the script will stop.
That's about it.
You can't. The php is first interpreted by the server and then send to the user as HTML-Code.
The only possibility would be creating a html-page and call the php-script with AJAX.
Related
I have a query in a CakePHP 3.0 table with a formatResults() method applied to it.
In order to carry out this calculation, data is required from a table in a different database (Currencies).
I am currently using this code to gather the data and pass it to the function:
$currencies = TableRegistry::get('Currencies');
$currencyValues = $currencies
->findByCurrno($options['currency'])
->cache('currency'.$options['currency']);
$currencyValues = $currencyValues->first()->toArray()
$query->formatResults(function ($results) use ($currencyValues) {
return $results->map(function($row) use ($currencyValues) {
$row['converted_earnings'] = $row['earned'] / $currencyValues['cur'.$row['currency']];
$row['converted_advances'] = $row['advances'] / $currencyValues['cur'.$row['currency']];
return $row;
});
});
The problem is, this code seems to take a very long time to execute, even though it is only iterating through a few hundred rows of data.
Further investigation revealed that if I do not collect the data from the 'currencies' table and instead declare $currencyValues as an array with fixed numbers the code takes a full second less to execute.
Through commenting out parts of the code, I have isolated this to be the cause of the problem:
$currencyValues = $currencies
->findByCurrno($options['currency'])
->cache('currency'.$options['currency']);
If I remove this part of the code then everything runs quickly, and as soon as I add it in (even if I do not use the data it returns and use the static array) the page takes far longer to load. It should be noted that this problem occurs whether or not I use the ->cache() method, and that the query itself reports that it takes 0-1ms in the sql dump.
My question is - why is this slowing down my execution so much and how can I stop it? It is pretty much a requirement that I use the data from this table for the operation, so I am looking for a way to speed it up.
Good morning.
I'm currently trying to build a very basic caching system for one of my scripts. The cache is JSON data and contains only 1 key and it's value, but many individual fields, something like this;
{"Item1":"Item1 Description"}
{"Item2":"Item2 Description"}
{"Item3":"Item3 Description"}
What I'm intending to do is;
First check if a cache file is available
Then check if an item exists in the cache
Then add the new item along with it's description if it's not already in the cache...
...or return the item description if it's not there.
All data being stored is strings. The cache file doesn't store any other type of data.
I've put together a basic function but I'm having trouble getting it functioning;
function ItemIsInCache($CacheFile, $ItemId) {
if(file_exists($CacheFile)) {
$json = json_decode(file_get_contents($CacheFile, true));
if(in_array($ItemId, $json)) { // <<
$itemname = array_search($ItemId, $json);
return itemname;
} else {
$item[$itemId] = GrabItemName($ItemId);
$itemname = array_search($ItemId, $json); // <<
return $itemname;
}
} else {
$item[$ItemId] = GrabItemName($ItemId);
$ejson = json_encode($item);
file_put_contents($CacheFile, $ejson);
return $item[$ItemId];
}
}
Notes
GrabItemName is a different function that returns the description data based on the $ItemId.
The warnings I'm getting are Wrong datatype for second argument in both array_search() and in_array(), on lines 4 and lines 9 respectively (those are the line numbers in the above code - due to the nature of my script these numbers are later on) -- for simplicity, I've marked the problem lines with // <<.
The function is running in a loop which I've no problems with. The problems lie within this function.
What currently happens
Right now, if the cache doesn't exist, it creates it and adds the first item from the loop to the cache file in it's respective JSON format (that fires since the cache file doesn't exist, so after the final else statement).
However, items from the loop after that don't get added, presumably because the file exists and there's something wrong with the code.
The last part of the function works exactly as I want it to but the first part does not.
Expected behaviour with fixed code
Check cache > Return description if item exists ELSE add new item to cache.
The items and their associated descriptions will NOT change, but I'm pulling them from a rate limited API, and I need to ensure I cache whatever I can for everyones benefit.
So, any ideas what I'm doing wrong with the function? I'm sure it's something incredibly simple that I'm overlooking.
Your file is not JSON for an erray. The correct JSON for an array is
[
{"Item1":"Item1 Description"},
{"Item2":"Item2 Description"},
{"Item3":"Item3 Description"}
]
You're missing the brackets around the array, so you just get a single object.
When creating the initial file, you need to do:
$ejson = json_encode(array($item));
so that it's initialized as an array of one item, not just an item.
I have this while loop, that basically loops through a lot of records in a database, and inserts the data in another:
$q = $con1->query($users1) or die(print_r($con2->errorInfo(),1));
while($row = $q->fetch(PDO::FETCH_ASSOC)){
$q = $con2->prepare($users2);
$q->execute(array($row['id'], $row['username'])) or die(print_r($con2-errorInfo(),1));
}
(The script has been shortened for easy reading - the correct one has a much longer array)
I would like to do this more graphical, and show a progress bar on how far it has went, instead of just seeing a page loading for a few minutes (there are ~20.000 rows in this one - I have tables with much more data)
I get that you could get the total number from the old database, and I could also easily put the current number into a variable like this:
$q = $con1->query($users1) or die(print_r($con2->errorInfo(),1));
$i = 0;
while($row = $q->fetch(PDO::FETCH_ASSOC)){
$q = $con2->prepare($users2);
$q->execute(array($row['id'], $row['username'])) or die(print_r($con2-errorInfo(),1));
$i++;
}
But now I need to actually fetch $i and display it - or something like it.
How is this "easily" done?
The code for the progress bar can either be in the same document as the while loop, or in another if easier.
You can do a "master" file that does an ajax to this first file to run a single query. You could get all the entry id's in this master file, and then pass it as a parameter to the second file that does a single query. Store these ids in a javascript array.
Create a function that does this, and when the first ajax is done, move to the second element of the id array, and do another ajax with a second parameter. That's how magento imports are done by the way :)
If you need further explanations, let me know, I tried my best to explain, but may have not been perfectly clear.
// you generate this javascript array using php.
// let's say you have all the ids that have to be processed in $Ids php array.
Ids = [<?php echo implode(',', $Ids); ?>];
function doAjax(i) {
$.ajax({ // using jquery for simplicity
'url': "ajax.php?id=" + Ids[i],
}).done(function(){
if ( i >= 0 ) {
// at the point you know you're at ((Ids.length-i)/(Ids.length) * 100) percent of the script
// so you can do something like this:
// $('.progressbar').css('width', ((Ids.length-i)/(Ids.length) * 100) + '%');
doAjax(i-1);
}
});
}
doAjax(Ids.length); // starting from the last entry
So, just to explain what this does. It starts by declaring a global javascript array that has all the ids that will need to be changed.
Then I declare a recursive ajax function, this way we can make sure that only one ajax runs at any single time (so the server doesn't blow up), and we can have a fairly accurate progress. This ajax function does the following:
Sends a request to ajax.php?id=xxx - where xxx is one of the ids in the javascript array.
In the file, we get the id ($_GET['id']), you take it from the old database, and insert it in the new one. This is only for one entry.
when the ajax is done, it goes to the done() function. Since we start the doAjax() function with the last element, we do the next iteration doAjax(i-1). Since we're going backwards in the array, we check if the key is positive. If it's not, the script will stop.
That's about it.
You can't. The php is first interpreted by the server and then send to the user as HTML-Code.
The only possibility would be creating a html-page and call the php-script with AJAX.
I have a PHP page that uses jQuery to let a user update a particular item without needing to refresh the page. It is an availability update where they can change their availability for an event to Yes, No, or Maybe. Each time they click on the link the appropriate jQuery function is called to send data to a separate PHP file (update_avail.php) and the appropriate data is returned.
Yes
Then when clicked the params are sent to a PHP file which returns back:
No
Then, if clicked again the PHP will return:
Maybe
It all works fine and I'm loving it.
BUT--
I also have a total count at the bottom of the page that is PHP code to count the total number of users that have selected Yes as their availability by simply using:
<?php count($event1_accepted); ?>
How can I make it so that if a user changes their availability it will also update the count without needing to refresh the page?
My thoughts so far are:
$var = 1;
while ($var > 0) {
count($day1_accepted);
$var = 0;
exit;
}
Then add a line to my 'update_avail.php' (which gets sent data from the jQuery function) to make $var = 1
Any help would be great. I would like to stress that my main strength is PHP, not jQuery, so a PHP solution would be preferred, but if necessary I can tackle some simple jQuery.
Thanks!
In the response from update_avail.php return a JSON object with both your replacement html and your new counter value.
Or to keep it simple, if they click "yes" incriment the counter, if they click No or maybe and their previous action wasn't No or Maybe decrease the counter.
Assuming your users are logged into the system I'd recommend having a status field in the user table, perhaps as an enum with "offline", "available", "busy", "unavailable" or something similar and use the query the number of available users whilst updating the users status.
If you were to do this you'd need to include in extend your methods containing session)start() and session_destroy() to change the availability of the user to available / offline respectively
The best way is the one suggested by Scuzzy with some improvements.
In your php, get the count from the database and return a JSON object like:
{ count: 123, html: 'Yes' }
In your page, in the ajax response you get the values and update the elements:
...
success: function(data) {
$("#linkPlaceholder").html(data.html);
$("#countPlaceholder").html(data.count);
}
...
I am trying to call back the value of content_columns to jquery.
PHP CODE:
if($act=="getcol"){
$pid=$_GET['pid'];
$domain_id = 1;
$PAGEresult = mysql_query("SELECT * FROM pages WHERE domain_id='$domain_id' AND id='$pid' ORDER BY id DESC");
$PAGErow = mysql_fetch_array($PAGEresult);
echo json_encode($PAGErow['content_columns']);
}
jQuery
$.get("get_actions.php?act=getcol&pid="+pid, function(data){
alert(data);
});
Can someone lead me down the right path please.
If by "same string" it is possible that it is cached. You can disable caching with jQuery's ajax library that you are using. You can also send a different query string such as with the system time to ensure you don't get a cached results. You can also use POST.
You will only ever get one result from that query. If you want multiple results, you need to iterate over mysql_fetch(). If you only want one result, add LIMIT 1 to your query. Otherwise it is incredibly wasteful. Finally, why use SELECT *? Use SELECT content_columns ..