I need a random string that refreshes every two seconds, so that you'll get an effect of a word that is mixed every two seconds. This is my code:
function rand_string( $length ) {
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$size = strlen( $chars );
for( $i = 0; $i < $length; $i++ ) {
$str .= $chars[ rand( 0, $size - 1 ) ];
}
return $str;
Then I want to repeat this a number of times, not unlimited, so I used this piece of code:
$random = rand_string( 9 );
for($i=0; $i < 5; $i++) {
echo $random;
flush();
sleep(2);
}
Somehow the page waits 10 seconds and then shows my string, and my string shows up five times the same, and not one time refreshing every two seconds. Could you please help me?
Try something like the example below. Substitute a URL that points at a page/service on your own server which returns the next string value (and nothing else). Be sure to set the content type in your response (from the server) to "text/plain".
As stated/indicated/hinted in other posts, the issue is that HTTP is a stateless protocol. The browser sends a request. The server sends a response. The end. :-) The PHP code executes exclusively on the server, where its job is only generating content for the web browser. But it does not interact with the browser in any way beyond that. Once all of the content generated by the PHP code is emitted to the browser, the PHP code is finished. You should read up a bit on concepts like output buffering. You can exercise a little bit of control over whether your PHP code buffers up all the output then sends it to the browser all-at-once, or trickles it out as it generates it. But you simply cannot use PHP code to interactively change anything on the web page. Once you send it to the browser, it's sent and that's it. You can't call it back and change it.
Now, having said that, you certainly can use PHP code to emit JavaScript code, which can then interact with the DOM in the browser, and also make AJAX calls back to different resources on the server, which can in turn be different PHP pages that do whatever you need them to and return results for display or for further processing in the browser (which could lead to additional AJAX calls to the server, although "chatty" does not generally equal "good").
AJAX (Asynchronous JavaScript and XML) is a technology that lets you make calls back to the web server from your web page without reloading the entire page. You can use JavaScript timer functions like setInterval() and setTimeout() to implement delays or to create recurring events, like your text update. Don't get too hung up on the "XML" in "AJAX." A newer data encapsulation standard called JSON has become very popular and is at least as usable via AJAX as XML is in virtually all cases. JSON is "JavaScript Object Notation," and the standard is basically just serialized JavaScript data structures, very natural to work with.
In fact, in the example I show below, neither XML nor JSON is utilized (in the interest of simplicity). But either XML or JSON could have easily been used and probably should be in a serious service implementation.
The XMLHttpRequest object is the magic bit that makes AJAX possible. XMLHttpRequest, setInterval(), setTimeout() and tons of other APIs utilize asynchronous callbacks. So that is another concept you will need to embrace. An asynchronous callback is just a function that you pass to, for example, setInterval() so that it will be able to "call you back" when the timer event occurs (you pass a reference to the function). In the meantime, your interface isn't locked up waiting for the callback. Thus it is asynchronous. My example below also uses inline (unnamed, anonymous) functions called closures, which is another concept that is very important for modern JavaScript programming.
Finally, I would heartily recommend using something like jQuery. Well, I'd recommend jQuery. There are other JavaScript frameworks, but I'm not entirely sure there is much point in looking at any of the others any more. The example below does not use jQuery.
The main thing you are accomplishing with your original example, since PHP executes exclusively on the server, is to make your page take longer to completely finish rendering, which means it takes longer for your request to disconnect from the web server, which in turn is tying up a connection resource on the server that no other browser instances can utilize until the request finishes at least 10 seconds after it starts.
<html>
<head>
</head>
<body>
<div id="blah">Watch me change.</div>
<script language="javascript">
// set callback function, to be called every 2 seconds
setInterval( function() {
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
}
else { // IE6, IE5
xmlhttp = new ActiveXObject( "Microsoft.XMLHTTP" );
}
// callback function called for each state change, "4" means request finished.
xmlhttp.onReadyStateChange = function() {
if( 4 == xmlhttp.readyState && 200 == xmlHttp.status ) {
document.getElementById("blah").innerHTML = xmlHttp.responseText;
}
}
xmlhttp.open( "GET", "http://source-of-new-string...", true );
xmlhttp.send();
}, 2000 );
</script>
</body>
</html>
You do not understand the fundamentals of web development yet. The single PHP script you wrote first generates a string, then loops 5 times, outputting the generated string and then sleeping for 2 seconds, and when the script is finished it is flushed to the browser. As such it's obvious that, since you only called the function once, you see 5 identical strings after 10 seconds.
Having a new string appear every 2 seconds is just not possible with the stateless thing that is an 'HTTP request'. You would need to use Ajax-callbacks to achieve that effect, invoked from the client side every 2 seconds.
header('Content-Type: text/html; charset=UTF-8');
function rand_string( $length ) {
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$size = strlen( $chars );
for( $i = 0; $i < $length; $i++ ) {
$str .= $chars[ rand( 0, $size - 1 ) ];
}
return $str;
}
for($i=0; $i < 5; $i++) {
$random = rand_string(9);
echo $random;
flush();
ob_flush();
sleep(2);
}
You need to define the variable $random new within the loop.
Somehow the page waits 10 seconds and then shows my string
First, PHP can't do what you wishes. PHP sends the web page content to the browser which in turn displays it.
So the browser may choose the amount of data that it needs to receive before even starting to display the page.
There is your delay: five times sleep(2);. The browser waits the end of the connection before displaying data.
My string shows up five times the same
Secondly, the code below only prints five times the content of the variable $random, which is never changed in the for loop. So five times the same content.
$random = rand_string( 9 );
for($i=0; $i < 5; $i++) {
echo $random;
flush();
sleep(2);
}
There is your repetition: five times echo $random;.
Notes
$random is a variable. For the rand() function, see here.
For random strings, see:
PHP random string generator
PHP may not be suited for what you want to do I need a random string
that refreshes every two seconds. The refreshing part could be obtained through javascript or at worst, by refreshing the page every two seconds and by displaying a new string along with the old ones. This will leave the illusion that a new string is added (with the ugly page loading moment in-between).
Related
I'm having a curiosity issue and don't seem to find the correct phrases for expressing what I mean, for a successful Google search query.
Some sites (that mostly do price queries) do an ajax query to something (let's assume it's php script) with user set criteria and the data doesn't get displayed all at once when the query is finished, but you see some parts being displayed from the response earlier (as I assume they become available earlier) and some later.
I'd imagine the ajax request is done to a php script which in turn queries different sources and returns data as soon as possible, meaning quicker query responses get sent first.
Core question:
How would such mechanism be built that php script can return data
multiple times and ajax script doesn't just wait for A response?
I'm rather sure there's information about this available, but unfortunately have not been able to find out even by what terms to search for it.
EDIT:
I though of a good example being cheap flight ticket booking services, which query different sources and seem to output data as soon as it's available, meaning different offers from different airlines appear at different times.
Hope someone can relieve my curiosity.
Best,
Alari
On client side you need onprogress. See the following example (copied from this answer):
var xhr = new XMLHttpRequest()
xhr.open("GET", "/test/chunked", true)
xhr.onprogress = function () {
console.log("PROGRESS:", xhr.responseText)
}
xhr.send()
xhr.responseText will keep accumulating the response given by the server. The downside here is that xhr.responseText contains an accumulated response. You can use substring on it for getting only the current response.
On the server side, you could do output buffering to chunk the response, e.g. like:
<?php
header( 'Content-type: text/html; charset=utf-8' );
for($i = 0; $i < 100; $i++){
echo "Current Response is {$i} \r\n";
flush();
ob_flush();
// sleep for 2 seconds
sleep(2);
}
I am tyring to make a php function that updates every second using php itself no other languages, just pure PHP codes.
function exp(){
//do something
}
I want it to return a value each second. Like update every second.
For an application server (not a web server), best practice is to use an event loop pattern instead of sleep. This gives you the ability to run multiple timers should the need arise (sleep is blocking so nothing else can run in the mean time). Web servers on the other hand should not really be executing any long-running scripts.
Whilst other languages give you event loops out of the box (node / js for example, with setInterval), PHP does not, so you have to either use a well known library or make your own). React PHP is a widely used event loop for PHP.
Here is a quick-and-dirty "hello world" implementation of an event loop
define("INTERVAL", 5 ); // 5 seconds
function runIt() { // Your function to run every 5 seconds
echo "something\n";
}
function checkForStopFlag() { // completely optional
// Logic to check for a program-exit flag
// Could be via socket or file etc.
// Return TRUE to stop.
return false;
}
function start() {
$active = true;
$nextTime = microtime(true) + INTERVAL; // Set initial delay
while($active) {
usleep(1000); // optional, if you want to be considerate
if (microtime(true) >= $nextTime) {
runIt();
$nextTime = microtime(true) + INTERVAL;
}
// Do other stuff (you can have as many other timers as you want)
$active = !checkForStopFlag();
}
}
start();
In the real world you would encapsulate this nicely in class with all the whistles and bells.
Word about threading:
PHP is single threaded under the hood (any OS threading must be manually managed by the programmer which comes with a significant learning curve). So every task in your event loop will hold up the tasks that follow. Node on the other hand, for example manages OS threads under the hood, taking that "worry" away from the programmer (which is a topic of much debate). So when you call setInterval(), the engine will work its magic so that the rest of your javascript will run concurrently.
Quick final note:
It could be argued that this pattern is overkill if all you want to do is have a single function do something every 5 seconds. But in the case where you start needing concurrent timers, sleep() will not be the right tool for the job.
sleep() function is the function that you are looking for:
while (true) {
my_function(); // Call your function
sleep(5);
}
While loop with always true
Call your function inside while loop
Wait for 5 seconds(sleep)
Return the beginning of the loop
By the way it's not a logical use case of endless loops in PHP if you are executing the script through a web protocol(HTTP, HTTPS, etc.) because you will get a timeout. A rational use case could be a periodic database updater or a web crawler.
Such scripts can be executed through command line using php myscript.php or an alternative (but not recommended) way is using set_time_limit to extend the limit if you insist on using a web protocol to execute the script.
function exp(){
//do something
}
while(true){
exp();
sleep(5);
}
Use sleep function to make execution sleep for 5 seconds
it will be better if you use setInterval and use ajax to perform your action
$t0 = microtime(true);
$i = 0;
do{
$dt = round(microtime(true)-$t0);
if($dt!= $i){
$i = $dt;
if(($i % 5) == 0) //every 5 seconds
echo $i.PHP_EOL;
}
}while($dt<10); //max execution time
Suppose exp() is your function
function exp(){
//do something
}
Now we are starting a do-while loop
$status=TRUE;
do {
exp(); // Call your function
sleep(5); //wait for 5 sec for next function call
//you can set $status as FALSE if you want get out of this loop.
//if(somecondition){
// $status=FALSE:
//}
} while($status==TRUE); //loop will run infinite
I hope this one helps :)
It's not preferable to make this in PHP, try to make on client side by calculating difference between time you got from database and current time.
you can make this in JS like this:
setInterval(function(){
// method to be executed;
},5000); // run every 5 seconds
My php script uses php simplehtmldom to parse html and get all the links and images that I want and this can run for a duration depending on the amount of images to download.
I thought it would be good idea to allow cancelling in this case. Currently I call my php using Jquery-Ajax, the closest thing I could find is php register_shutdown_function but not sure if it can work for my case. Any ideas?
So once php is launched, it cant be disturbed? like fire ajax again to call an exit to the same php file?
This is good only in case you are processing really massive data loads through AJAX. For other cases, just handle it in JS to not display result if canceled.
But as I said If you are processing huge loads of data, then you can add a interrupt condition in every nth step of running script and fulfill that condition using another script. For example you can use a file to store a interrupt data, or MySQL MEMORY table.
Example.
1, process.php (ajax script processing loads of data)
// clean up previous potential interrupt flag
$fileHandler = fopen('interrupt_condition.txt', 'w+');
fwrite($fileHandler, '0');
fclose($fileHandler);
function interrupt_check() {
$interruptfile = file('interrupt_condition.txt');
if (trim($interruptfile[0]) == "1") { // read first line, trim it and parse value - if value == 1 interrupt script
echo json_encode("interrupted" => 1);
die();
}
}
$i = 0;
foreach ($huge_load_of_data as $object) {
$i++;
if ($i % 10 == 0) { // check for interrupt condition every 10th record
interrupt_check();
}
// your processing code
}
interrupt_check(); // check for last time (if something changed while processing the last 10 entries)
2, interrupt_process.php (ajax script to propagate cancel event to file)
$fileHandler = fopen('interrupt_condition.txt', 'w+');
fwrite($fileHandler, '1');
fclose($fileHandler);
This will definitely affect performance of your script, but makes you a backdoor to close execution. This is very simple example - you need to make it more complex to make it work for more users simultaneously, etc.
You can also use MySQL MEMORY Table, MEMCACHE - Non-persistent Caching Server or whatever non-persistent storage you could find.
I have some PHP code that is receiving and processing large images. I'd like to echo out some JavaScript at certain points while the image is being processed to update the DOM with jQuery. Here is some sample code, but it isn't working. It just waits the entire 5 seconds and then makes the alerts happen back to back. I want it to do the first alert immediately and then next alert after 5 seconds.
ob_start();
echo '<script type="text/javascript">alert(\'1...\');</script>';
ob_flush();
sleep(5);
ob_start();
echo '<script type="text/javascript">alert(\'2...\');</script>';
ob_flush();
Can anyone help?
Most browsers buffer content until a certain size is reached. Try making your script blocks longer by padding them with something.
Also: You should call flush, not just ob_flush, and make sure zlib compression is turned off.
I have some PHP code that is receiving and processing large images. I'd like to echo out some JavaScript at certain points while the image is being processed to update the DOM with jQuery.
This may be out-of-scope for what you have to get done, but I'd use AJAX for this. You can certainly get what you want to occur, but the approach isn't good in the long term.
Instead of submitting the whole page and waiting for it to come back at a crawl, use an AJAX request to upload the image and get the result. Then a timer on the client can issue separate AJAX "how far done are you?" requests. The two PHP instances would communicate via setting a "done" flag on the job entry in a database, etc.
While it makes the client-side stuff a bit more complex, it is much easier to handle user interaction (such as allowing the user to cancel a long-running job) and makes your PHP code a lot more tightly-focused.
Adding this to the top of the script will work:
for ($i = 0; $i < ob_get_level(); $i++) { ob_end_flush(); }
ob_implicit_flush(1);
As far as I know, ob_implicit_flush(1) forces a flush on every output statement. So the other ob_start() and ob_flush() calls wouldn't be necessary. I don't know if that works for you.
<?php
for ($i = 0; $i < ob_get_level(); $i++) { ob_end_flush(); }
ob_implicit_flush(1);
echo '<script type="text/javascript">alert(\'1...\');</script>';
sleep(5);
echo '<script type="text/javascript">alert(\'2...\');</script>';
?>
Following is working in FF4:
<?php
echo '<script type="text/javascript">alert("1");</script>';
flush();
sleep(5);
echo '<script type="text/javascript">alert("2");</script>';
?>
I implemented a chat "server" with something like that long ago. It was working.
This ob_* stuff isn't helpful for this.
I have a continuously generated data (text file) generated by a program on the server. I want to plot the data as a real-time graph just like powergrid does. This was my approach:
As the data is generated continuously on the server in a text file, I wrote a PHP script which reads that file(get_file_contents), outputs the data points and plot the graph using sparkline jQuery plugin. But the problem is that it reads the file all at once. Moreover, the text file keeps on growing. Can anyone suggest me a better approach?
As you're talking about using a Javascript plotting solution you do the following:
on page load you create the current graph by reading the complete text file and remembering it's size.
after the page is loaded you create a Javascript function that regularly polls a specific script on your server using AJAX-techniques (XMLHttpRequest) and passing the last-known filesize of your text file as a parameter.
your polling script takes the filesize parameter, opens the text file, skips through the file until it reaches the point from which you last read the file (filesize-parameter).
the polling script returns all the available data from filesize to the end of the file and the new filesite
your Javascript reads in the AJAX response and adds the required plot points to your graph
you can then start over polling your server-side script with the new filesize as a parameter
This procedure involves server-side as well as client-side programming but can be accomplished easily.
The following is a sample polling script that requires a index paramater that tells the script from which position to read the text file and returns a JSON-encoded list of plot points and the new index pointer.
// poll.php
$index = (isset($_GET['index'])) ? (int)$_GET['index'] : 0;
$file = fopen('path/to/your/file.txt', 'r');
$data = array(
'index' => null,
'data' => array()
);
// move forward to the designated position
fseek($file, $index, SEEK_SET);
while (!feof($file)) {
/*
* assuming we have a file that looks like
* 0,10
* 1,15
* 2,12
* ...
*/
list($x, $y) = explode(',', trim(fgets($handle)), 2);
$data['data'][] = array('x' => $x, 'y' => $y);
}
// set the new index
$data['index'] = ftell($file);
fclose($file);
header('Content-Type: application/json');
echo json_encode($data);
exit();
The corresponding Javascript/jQuery snippet could be:
// the jQuery code to poll the script
var current = 0;
function pollData() {
$.getJSON('poll.php', { 'index': current }, function(data) {
current = data.index;
for (var i= 0; i < data.data.length; i++) {
var x = data.data[i].x;
var y = data.data[i].y;
// do your plotting here
}
});
}
// call pollData() every 5 seconds
var timer = window.setInterval(pollData, 5000);
Please be careful that this is only an example and that it lacks all error checking (e.g. concurrent calls to pollData() on the same page will be problematic).
It sounds like you have the visualization part mostly worked out. If the dataset is too large to re-calculate, you may want to look into techniques for maintaining incremental histograms. Here are a few papers that may help:
The history of histograms (abridged)
Random Sampling for Histogram Construction: How much is enough?
Data-Streams and histograms
Fast Incremental Maintenance of Approximate Histograms
First off, I would not generate the graph on the user side. That has simple reasons: Not everyone has JavaScript enabled (okay, depends on your target group) and it is probably not very fast.
Since you are already using PHP, I would therefore recommend using a package like pChart for creating the graphs on the server side. Another positive side-effect of this is that said package comes with caching, too. This would, for example, allow you to create the graph only when the data text file is changed (assuming you generate that with PHP, too - else you can simply check if the file was modified every time your PHP script is run) and thus saving loads of resources ;)