How to update variables while page in Infinite loop in PHP? - php

I have something like this :
<?php
$perform_check = 1; #Checks data with ID : 1
while(true)
{
#code
}
?>
But some data must be updated in this process, is it possible to update this data from another document?
I tried something like this :
index.php
<?php
setcookie("data", 19, time()+3600);
?>
and
loop.php
<?php
while(true)
{
if($perform_check!=$_COOKIE[data]) $perform_check = $_COOKIE[data];
#rest of code
flush();
sleep(0.3);
}
?>
But it doesn't work. I also tried $_SESSION but the page crashes on session_start().
Is it somehow possible?

Cookies are sent as a HTTP header when PHP is sending a response through the web server (for example Apache2).
All HTTP headers are sent before any output. If you output anything, headers are sent (including the set-cookie header) before the output.
After you flush() the first time you can no longer set cookies or other headers.
If you want a progress indicator or updates, you need to initiate whatever operation you are doing using javascript and do polling at an interval. In the process with the loop you need to save the progress in a shared memory, in a file or in a database (in this order of preference), then read that data using the process started by javascript progress check/updates check.

You could use the existence of a file to flag the ending of the process. For example, create a lock file,
$lock_file = <some unique name>
fopen($lock_file, 'w') or die("can't open file");
while ( file_exists($lock_file)) {
.
.
doStuff();
.
.
}
If the file is removed by some other process, it should terminate.

I think a while loop isn't doing any good here. you should look into php websocket implementation. It's an implementation in PHP to have websockets and to have a open connection with your user. If you have that you can manage things with listeners on both sides.

If you want the value to change while your code is looping, you need to check if the value has changed within the loop, not before.
A cookie or session will only work if the same user/browser is running both scripts. Writing to a file or database is the more usual approach.

I'm not quite sure about what you really want to do here.. but i guess you could do this..
<?php
$perform_check = 1; #Checks data with ID : 1
while(true) : ?>
$.ajax({
type:'post',
data: //your data to be passed to ajax script..
url: //the script wherein you want to run the query..
onSuccess: function(data) {
if(data==test) {
//if you have data that you want then you could stop the loop
<?php $perform_check = false; ?>
}
}
});
<?php endwhile: ?>
Hope this helps.

If you need to check very often you should use a CRON that calls the function you use to check.

Related

Running an external php code asynchronously

I am building a WebService, using PHP:
Basically,
User sends a request to the server, via HTTP Request. 'request.php', ie.
Server starts php code asynchronously. 'update.php', ie.
The connection with the user is finished.
The code 'update.php' is still running, and will finish after some time.
The code 'update.php' is finished.
The problem is with php running asynchronously some external code.
Is that possible? Is there another way to do it? With shell_exec?
Please, I need insights! An elegant way is preferable.
Thank you!
The best approach is using message queue like RabbitMQ or even simple MySQL table.
Each time you add new task in front controller it goes to queue. Then update.php run by cron job fetch it from queue, process, save results and mark task as finished.
Also it will help you distribute load over time preventing from DoS caused by your own script.
You could have the user connect to update.php, generate some sort of unique ID to keep track of the process, and then call fsockopen() on itself with a special GET variable to signify that it's doing the heavy lifting rather than user interaction. Close that connection immediately, and then print out the appropriate response to the user.
Meanwhile, look for the special GET variable you specified, and when present call ignore_user_abort() and proceed with whatever operations you need in that branch of the if clause. So here's a rough skeleton of what your update.php file would look like:
<?php
if ( isset($_GET['asynch']) ) {
ignore_user_abort();
// check for $_GET['id'] and validate,
// then execute long-running code here
} else {
// generate $id here
$host = $_SERVER['SERVER_NAME'];
$url = "/update.php?asynch&id={$id}";
if ( $handle = fsockopen($host, 80, $n, $s, 5) ) {
$data = "GET {$url} HTTP/1.0\r\nHost: {$host}\r\n\r\n";
fwrite($handle, $data);
fclose($handle);
}
// return a response to the user
echo 'Response goes here';
}
?>
You could build a service with PHP.
Or launch a PHP script using bash : system("php myScript.php param param2 &")
Look into worker processes with Redis resque or gearman

Stop PHP with ajax

I have a JavaScript functions which calls a PHP function through AJAX.
The PHP function has a set_time_limit(0) for its purposes.
Is there any way to stop that function when I want, for example with an HTML button event?
I want to explain better the situation:
I have a php file which uses a stream_copy_to_stream($src, $dest) php function to retrieve a stream in my local network. The function has to work until I want: I can stop it at the end of the stream or when I want. So I can use a button to start and a button to stop. The problem is the new instance created by the ajax call, in fact I can't work on it because it is not the function that is recording but it is another instance. I tried MireSVK's suggest but it doesn't worked!
Depending on the function. If it is a while loop checking for certain condition every time, then you could add a condition that is modifiable from outside the script (e.g. make it check for a file, and create / delete that file as required)
It looks like a bad idea, however. Why you want to do it?
var running = true;
function doSomething(){
//do something........
}
setInterval(function(){if(running){doSomething()}},2000); ///this runs do something every 2 seconds
on button click simply set running = false;
Your code looks like:
set_time_limit(0);
while(true==true){//infinite loop
doSomething(); //your code
}
Let's upgrade it
set_time_limit(0);
session_start();
$_SESSION['do_a_loop'] = true;
function should_i_stop_loop(){
#session_start();
if( $_SESSION['do_a_loop'] == false ) {
//let's stop a loop
exit();
}
session_write_close();
}
while(true==true){
doSomething();
should_i_stop_loop(); //your new function
}
Create new file stopit.php
session_start();
$_SESSION['do_a_loop'] = false;
All you have to do now is create a request on stopit.php file (with ajax or something)
Edit code according to your needs, this is point. One of many solutions.
Sorry for my English
Sadly this isn't possible (sort of).
Each time you make an AJAX call to a PHP script the script spawns a new instance of itself. Thus anything you send to it will be sent to a new operation, not the operation you had previously started.
There are a number of workarounds.
Use readystate 3 in AJAX to create a non closing connection to the PHP script, however that isn't supported cross browser and probably won't work in IE (not sure about IE 10).
Look into socket programming in PHP, which allows you to create a script with one instance that you can connect to multiple times.
Have PHP check a third party. I.E have one script running in a loop checking a file or a database, then connect to another script to modify that file or database. The original script can be remotely controlled by what you write to the file/database.
Try another programming language (this is a silly option, but I'm a fan of node). Node.js does this sort of thing very very easily.

Tracking changes in text file with PHP

I have a PHP script that has to reload a page on the client (server push) when something specific happens on the server. So I have to listen for changes. My idea is to have a text file that contains the number of page loads for the current page. So I would like to monitor the file and as soon as it is modified, to use server push in order to update the content on the client. The question is how to track the file for changes in PHP?
You could do something like:
<?php
while(true){
$file = stat('/file');
if($file['mtime'] == time()){
//... Do Something Here ..//
}
sleep(1);
}
This will continuously look for a change in the modified time of a file every second. If you don't constrain it you could kill your disk IO and may need to adjust your ulimit.
This will check your file for a change:
<?php
$current_contents = "";
function checkForChange($filepath) {
global $current_contents;
$new_contents = file_get_contents($filepath);
if (strcmp($new_contents, $current_contents) {
$current_contents = $new_contents;
return true;
}
return false;
}
But that will not solve your problem. The php file that serves the client finishes executing before the rendered html is sent to the client. That client will need to call back to some php file to check for a change... and since that is also a http request, the file will finish executing and forget anything in memory.
In order to properly solve this, you'll probably have to back off the idea of checking a file. Either the server needs to know when and how to contact currently connected clients, or those clients need to poll a lightweight service at a regular interval.
This is sort of hacky but what about creating a cron job that sucks in the page, stores it in a scope or table, and then simply compares it every 30 seconds?

using ignore_user_abort and set_time_limit(0)

I have a form in page1.php which both redirects to page3.php and also triggers an ajax post in page2.php (with no success function), page2.php might need to run for an hour, but the user doesn't need the results. I do need the user to see page2.php, but he might navigate away.
Do I need to use in page2.php these 2 functions? Or just one of them? Or none? I want to make sure the script in page2.php runs until the end.
Page1.php
<form id="form" action="page2.php" method="post">
<!--form input elements with names-->
</form>
<script>
$('#form').submit(function() {
$.post('page3.php', {
var1: $('input[name="name1"]').val(),
var2: $('input[name="name2"]').val(),
});
});
</script>
Page2.php
<?php
ignore_user_abort(true); // Allow user to navigate away
set_time_limit(0); // Allow script to run indefinitely
// a lot of code which will run for a while - between 3 minutes and an hour
?>
Page3.php
<html>
<!--some code here including links to go to page4.php-->
</html>
I am asking partly because I thought there is no need for any of these functions, but was told to use them, but when I try using them, eventhough there is die(); and the script stops, it still seems to be processsing something and I'm afraid because of this "indefinitely" it will be too much on the server.
As I don't want to add unnecessary loads.
Yes you would need both of those functions in order to accomplish your current criteria, my suggestion would be to move this out of the http protocal. Depending on what your script is actually accomplishing if it requires no further interaction from the client it would be best used in the command line.
A theory of use would be to create a cron script that is called at the needed intervals, it would then access a queue which page2.php would populate.
If there is a queue available the cron script would process the information as it is currently done on page2.php. Since your script runs for a long period of time I would suggest using a locking mechanism for the cron, see php.net/flock for a simple file system lock. You check the file if its locked its already running.
Here is a simple example that you put into a standalone script for processing via cron:
$fp = fopen(DATA_PATH . '/locks/isLocked', 'w+');
if (!flock($fp, LOCK_EX | LOCK_NB)) { //locks the file
$logger->info('Already Running');
exit(0);
}
fwrite($fp, time()); //write our new time so we can inspect when it ran last if needed
try {
if (hasQueue()) { //checks to see if any jobs are waiting in mysql
run(); //process normally completed by page2.php
}
} catch (Exception $e) {
//something went wrong here could setup a log / email yourself etc..
}
flock($fp, LOCK_UN); //unlock the file

Using Jquery to update a page when a database is modified

I want to update a page when my database is modified. I want to use jquery for doing this. Question not clear? Then have a look at this, Suppose this is my page:
<?php
$query=mysql_query("select * from tbl1 where user='admin'");
if(mysql_num_rows?($query)!=0)
{
echo 'Table 1 has values';
} else {
echo 'Table1 is empty';
}
?>
This action should be performed whenever any new entry is added to the database. Now suppose I add an entry to the database manually then the page should automatically show the result as "Table1 has values". I know it can be used by using refresh page periodically but I don't want to use it. Instead I want to try something other, like ajax polling? Can someone give me a demo?
You can use long polling, but do a lot of research first. Your server may kill the request that appears to be open for a long amount of time.
In PHP, your code will look something like...
set_time_limit(0);
while (TRUE) {
// Query database here
if ($results) {
echo json_encode($results);
exit;
}
sleep(1);
}
You can use Ajax jQuery Framework with Ajax:
http://www.w3schools.com/Ajax/default.asp
http://api.jquery.com/jQuery.ajax/
It will call the server side script Asynchronously and update your page accordingly. You can use jQuery to specify the format of the update also.
You are looking for Ajax-Push/Comet solutions. These aren't trivial.
You also mentioned ajax pooling.
Well, on the server side you need to loop until you have a timeout (that you defined yourself or the server did, make sure you return the HTTP status code for Timeout Occured) or the request can be satisfied.
And on the client side whenever you complete the operation successfully just handle it and than make the same ajax call again, if you timed out just make the same ajax request again until it's satisfied.

Categories