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
Related
I have a PHP script that processes data downloaded from multiple REST APIs into a standardized format and builds an array or table of this data. The script currently executes everything synchronously and therefore takes too long.
I have been trying to learn how to execute the function that fetches and processes the data, simultaneously or asynchronously so that the total time is the time of the slowest call. From my research it appears that ReactPHP or Amp are the correct tools.
However, I have been unsuccessful in creating test code that actually executes correctly. A simple example is attached, with mysquare() representing my more complex function. Due to a lack of examples on the net of exactly what I'm trying to achieve I have been forced to use a brute force method with 3 examples listed in my code.
Q1: Am I using the right tool for the job?
Q2: Can you fix my example code to execute asynchronously?
NB: I am a real beginner, so the simplest possible code example with a minimum of high level programming lingo would be appreciated.
<?php
require_once("../vendor/autoload.php");
for ($i = 0; $i <= 4; $i++) {
// Experiment 1
$deferred[$i] = new React\Promise\Deferred(function () use ($i) {
echo $x."\n";
usleep(rand(0, 3000000)); // Simulates long network call
return array($x=> $x * $x);
});
// Experiment 2
$promise[$i]=$deferred[$i]->promise(function () use ($i) {
echo $x."\n";
usleep(rand(0, 3000000)); // Simulates long network call
return array($x=> $x * $x);
});
// Experiment 3
$functioncall[$i] = function () use ($i) {
echo $x."\n";
usleep(rand(0, 3000000)); // Simulates long network call
return array($x=> $x * $x);
};
}
$promises = React\Promise\all($deferred); // Doesn't work
$promises = React\Promise\all($promise); // Doesn't work
$promises = React\Promise\all($functioncall); // Doesn't work
// print_r($promises); // Doesn't return array of results but a complex object
// This is what I would like to execute simulatenously with a variety of inputs
function mysquare($x)
{
echo $x."\n";
usleep(rand(0, 3000000)); // Simulates long network call
return array($x=> $x * $x);
}
Asynchronous doesn't mean multiple threads execute in parallel. 2 functions can only really run at the 'same time', if they (for example) do IO such as a HTTP request.
usleep() blocks, so you gain nothing. Both ReactPHP and Amp will have some kind of 'sleep' function themselves that's built right into the event loop.
For the same reason you will not be able to just use curl, because it will also block out of the box. You need to use the HTTP libraries that React and Amp provide and/recommend.
Since your end-goal is just doing HTTP requests, you could also not use any of these frameworks and just use the curl_multi functions. They're a bit hard to use though.
I'm answering my own question in an attempt to help other users, however this solution was developed alone without the help of an experienced programmer and so I do not know if it is ultimately the best way to do this.
TL;DR
I switched from ReactPHP because I didn't understand it to using amphp/parallel-functions which offers a simplified end user interface... sample code using this interface attached.
<?php
require_once("../vendor/autoload.php");
use function Amp\ParallelFunctions\parallelMap;
use function Amp\Promise\wait;
$start = \microtime(true);
$mysquare = function ($x) {
sleep($x); // Simulates long network call
//echo $x."\n";
return $x * $x;
};
print_r(wait(parallelMap([5,4,3,2,1,6,7,8,9,10], $mysquare)));
print 'Took ' . (\microtime(true) - $start) . ' milliseconds.' . \PHP_EOL;
The example code executes in 10.2 seconds which is slightly longer than the longest running instance of $mysquare().
In my actual use case I was able to fetch data via HTTP from 90 separate sources in around 5 seconds.
Notes:
The amphp/parallel-functions library appears to be using threads under the hood. From my preliminary experience this appears to require a lot more memory than just a single threaded PHP script, but I haven't yet ascertained the full impact. This was highlighted when I was passing a large array to $mysquare via the "use ($myarray)" expression and array was 65Mb. This brought the code to a standstill and it increased execution time exponentially so much so that it took orders of magnitude longer than synchronous execution. Also the memory usage peaked at over 5G! at one point leading me to believe that amphp was duplicating $myarray for each instance. Reworking my code to avoid the "use ($myarray)" expression fixed that problem.
I have a web page that contains some JavaScript and performs some Ajax calls. When trying to test it using Selenium, I randomly get "PHPUnit_Extensions_Selenium2TestCase_WebDriverException: Element is no longer attached to the DOM" message, maybe once in 5 runs.
Now I'm aware of the race issue between Ajax call and test engine, and I have taken steps to protect from it, but I still have some problem. My scenario is this: I change value of the select element 1 which triggers Ajax call that removes all option sub-elements of the select element 2 and generates new option sub-elements based on the Ajax response. Testing code:
$this->select($this->byId('select1'))->selectOptionByValue('value1');
$this->myWaitForElementToAppear('#select2>option[value="value2"]');
$this->select($this->byId('select2'))->selectOptionByValue('value2');
last line triggers the error. Here is the myWaitForElementToAppear method:
public function myWaitForElementToAppear($selector, $limit = 5) {
$start = time();
while(true) {
if($start + $limit < time()) {
break;
}
try {
$this->byCssSelector($selector);
break;
} catch(PHPUnit_Extensions_Selenium2TestCase_WebDriverException $e) {}
}
}
If I'm not mistaken, myWaitForElementToAppear method should ensure that desired option has been added by jQuery before it exits and thus allow it to be used on the next line. I should add that I've made sure that time-out doesn't happen here (since my method allows for it to happen) and I'm positive that it's not the case
Edit: I should add that putting sleep(1) after myWaitForElementToAppear call solves the problem, but I don't understand why the additional second is needed. Shouldn't call to myWaitForElementToAppear be enough?
There are some explanations here:
Firstly, time() has a very low precision, only returning the number of
whole seconds that have passed, which makes the whole thing quite
vague. Secondly, PHP has to sit there looping thousands of times while
it waits, essentially doing nothing. A much better solution is to use
the one of the two script sleep functions, sleep() and usleep(), which
take the amount of time to pause execution as their only parameter.
From php.net:
The idea of sleep and usleep is that by letting the cpu run a few idle
cycles so the other programs can have some cycles run of their own.
what results in better response times and lower overall system-load.
so if you have to wait for something, go to sleep for a few seconds
instead of occupying the cpu while doing absolute nothing but
waitting.
And you can use waitUntil from PHPUnit:
/* waitElementToDisappear */
$this->waitUntil(function($testCase) {
try {
$input = $testCase->byCssSelector("#select2>option[value="value2"]");
} catch (PHPUnit_Extensions_Selenium2TestCase_WebDriverException $e) {
if (PHPUnit_Extensions_Selenium2TestCase_WebDriverException::NoSuchElement == $e->getCode()) {
return true;
}
}
}, 5000);
/* waitElementToAppear */
$this->waitUntil(function($testCase) {
try {
$input = $testCase->byCssSelector("#select2>option[value="value2"]");
return true;
} catch (PHPUnit_Extensions_Selenium2TestCase_WebDriverException $e) {}
}, 5000);
In PHP, I want to put a number of second delay on each iteration of the loop.
for ($i=0; $i <= 10; $i++) {
$file_exists=file_exists($location.$filename);
if($file_exists) {
break;
}
//sleep for 3 seconds
}
How can I do this?
Use PHP sleep() function. http://php.net/manual/en/function.sleep.php
This stops execution of next loop for the given number of seconds. So something like this
for ($i=0; $i <= 10; $i++) {
$file_exists=file_exists($location.$filename);
if($file_exists) {
break;
}
sleep(3); // this should halt for 3 seconds for every loop
}
I see what you are doing... your delaying a script to constantly check for a file on the filesystem (one that is being uploaded or being written by another script I assume). This is a BAD way to do it.
Your script will run slowly. Choking the server if several users are running that script.
Your server may timeout for some users.
HDD access is a costly resource.
There are better ways to do this.
You could use Ajax. And use a timeout to call your PHP script every few seconds. This will avoid the slow script loading. And also you can keep doing it constantly (the current for loop will only run for 33 seconds and then stop).
You can use a database. In some cases database access is faster than HDD access. Especially with views and caching. The script creating the file/uploading the file can set a flag in a table (i.e. file_exists) and then you can have a script that checks that field in your database.
You can use sleep(3) which sleeps the thread for 3 seconds.
Correction sleep method in php are in seconds.
Hare are two ways to sleep php script for some period of time. When you have your code and want to pause script working for some time use these functions.
In these examples the first part of code will be done on script run and the second part of code will be done but with time delay.
Using sleep() function you can define sleep time in seconds.
Example:
echo "Message 1";
// The first part of code.
$timeInSeconds = 3;
sleep($timeInSeconds);
// The second part of code.
echo "Message 2";
This way it is possible to sleep php script for 3 seconds. Using this function you can sleep script for whole number (integer) of seconds.
Using usleep() function you can define sleep time in microseconds. This sleep time is convenient for intervals that require more precise time than one second.
Example:
echo "Message 1";
// The first part of code.
$timeInMicroSeconds = 2487147;
usleep($timeInMicroSeconds);
// The second part of code.
echo "Message 2";
You can use this function if you want to sleep php for smaller time values than second (float). In this example I have put script to sleep for 2.487147 seconds.
Have you considered using a PHP Daemon script using supervisorD. I use it in multiple tasks that are required to be running all the time.
The catch is making sure that each time you are running your script you check for memory resources. If its too high, stop the process and then let it restart itself up again.
I have successfully used this process to be always checking database records for tasks to process.
It might be overkill but worth considering.
I'd like to limit a specific section of PHP to X seconds - if it takes longer, kill the currently executing code (just the section, not the entire script) and run an alternate code.
Pseudo code example (Example use case here is an unstable API which is sometimes fast and other times its a black hole):
$completed = 1;
$seconds = 60;
while ($completed != -1 && $completed < 5) {
limit ($seconds) {
$api = new SomeAPI('user','secret','key');
$data = $api->getStuff('user="bob"');
$completed = -1;
} catch () {
$completed++;
sleep(10);
}
}
if ($completed === 5) echo "Error: API black-hole'd 5 times.\n";
else {
//Notice: data processing is OUTSIDE of the time limit
foreach ($data as $row) {
echo $row['name'].': '.$row['message']."\n";
}
}
HOWEVER, this should work for anything. Not just API/HTTP requests. E.g. an intensive database procedure.
In case you're reading too fast: set_time_limit and max_execution_time are not the answer as they affect the time limit for the entire script rather than just a section (unless I'm wrong on how those work, of course).
In the case of an API call, I would suggest using cURL, for which you can set a specific timeout for the API call.
For generic use, you can look at forking processes, which would give you the ability to time each process and kill it if it exceeds the expected time.
Of course if the section of code might be subject to long execution times due to a highly repetitive loop structure, you can provide your own timers to break out of the loop after a specified time interval.
I might not have directly answered your question, but really the point I wanted to get to is that you might have to use a different approach depending on what the code block actually does.
The question sort of says it all - is there a function which does the same as the JavaScript function setTimeout() for PHP? I've searched php.net, and I can't seem to find any...
There is no way to delay execution of part of the code of in the current script. It wouldn't make much sense, either, as the processing of a PHP script takes place entirely on server side and you would just delay the overall execution of the script. There is sleep() but that will simply halt the process for a certain time.
You can, of course, schedule a PHP script to run at a specific time using cron jobs and the like.
There's the sleep function, which pauses the script for a determined amount of time.
See also usleep, time_nanosleep and time_sleep_until.
PHP isn't event driven, so a setTimeout doesn't make much sense. You can certainly mimic it and in fact, someone has written a Timer class you could use. But I would be careful before you start programming in this way on the server side in PHP.
A few things I'd like to note about timers in PHP:
1) Timers in PHP make sense when used in long-running scripts (daemons and, maybe, in CLI scripts). So if you're not developing that kind of application, then you don't need timers.
2) Timers can be blocking and non-blocking. If you're using sleep(), then it's a blocking timer, because your script just freezes for a specified amount of time.
For many tasks blocking timers are fine. For example, sending statistics every 10 seconds. It's ok to block the script:
while (true) {
sendStat();
sleep(10);
}
3) Non-blocking timers make sense only in event driven apps, like websocket-server. In such applications an event can occur at any time (e.g incoming connection), so you must not block your app with sleep() (obviously).
For this purposes there are event-loop libraries, like reactphp/event-loop, which allows you to handle multiple streams in a non-blocking fashion and also has timer/ interval feature.
4) Non-blocking timeouts in PHP are possible.
It can be implemented by means of stream_select() function with timeout parameter (see how it's implemented in reactphp/event-loop StreamSelectLoop::run()).
5) There are PHP extensions like libevent, libev, event which allow timers implementation (if you want to go hardcore)
Not really, but you could try the tick count function.
http://php.net/manual/en/class.evtimer.php is probably what you are looking for, you can have a function called during set intervals, similar to setInterval in javascript. it is a pecl extension, if you have whm/cpanel you can easily install it through the pecl software/extension installer page.
i hadn't noticed this question is from 2010 and the evtimer class started to be coded in 2012-2013. so as an update to an old question, there is now a class that can do this similar to javascripts settimeout/setinterval.
Warning: You should note that while the sleep command can make a PHP process hang, or "sleep" for a given amount of time, you'd generally implement visual delays within the user interface.
Since PHP is a server side language, merely writing its execution output (generally in the form of HTML) to a web server response: using sleep in this fashion will generally just stall or delay the response.
With that being said, sleep does have practical purposes. Delaying execution can be used to implement back off schemes, such as when retrying a request after a failed connection. Generally speaking, if you need to use a setTimeout in PHP, you're probably doing something wrong.
Solution: If you still want to implement setTimeout in PHP, to answer your question explicitly: Consider that setTimeout possesses two parameters, one which represents the function to run, and the other which represents the amount of time (in milliseconds). The following code would actually meet the requirements in your question:
<?php
// Build the setTimeout function.
// This is the important part.
function setTimeout($fn, $timeout){
// sleep for $timeout milliseconds.
sleep(($timeout/1000));
$fn();
}
// Some example function we want to run.
$someFunctionToExecute = function() {
echo 'The function executed!';
}
// This will run the function after a 3 second sleep.
// We're using the functional property of first-class functions
// to pass the function that we wish to execute.
setTimeout($someFunctionToExecute, 3000);
?>
The output of the above code will be three seconds of delay, followed by the following output:
The function executed!
if you need to make an action after you execute some php code you can do it with an echo
echo "Success.... <script>setTimeout(function(){alert('Hello')}, 3000);</script>";
so after a time in the client(browser) you can do something else, like a redirect to another php script for example or echo an alert
There is a Generator class available in PHP version > 5.5 which provides a function called yield that helps you pause and continue to next function.
generator-example.php
<?php
function myGeneratorFunction()
{
echo "One","\n";
yield;
echo "Two","\n";
yield;
echo "Three","\n";
yield;
}
// get our Generator object (remember, all generator function return
// a generator object, and a generator function is any function that
// uses the yield keyword)
$iterator = myGeneratorFunction();
OUTPUT
One
If you want to execute the code after the first yield you add these line
// get the current value of the iterator
$value = $iterator->current();
// get the next value of the iterator
$value = $iterator->next();
// and the value after that the next value of the iterator
// $value = $iterator->next();
Now you will get output
One
Two
If you minutely see the setTimeout() creates an event loop.
In PHP there are many libraries out there E.g amphp is a popular one that provides event loop to execute code asynchronously.
Javascript snippet
setTimeout(function () {
console.log('After timeout');
}, 1000);
console.log('Before timeout');
Converting above Javascript snippet to PHP using Amphp
Loop::run(function () {
Loop::delay(1000, function () {
echo date('H:i:s') . ' After timeout' . PHP_EOL;
});
echo date('H:i:s') . ' Before timeout' . PHP_EOL;
});
Check this Out!
<?php
set_time_limit(20);
while ($i<=10)
{
echo "i=$i ";
sleep(100);
$i++;
}
?>
Output:
i=0 i=1 i=2 i=3 i=4 i=5 i=6 i=7 i=8 i=9 i=10