Recursive PHP function doesn't stop and freezes my browser - php

I have the following recursive function:
$cogs = array('hello', 'how', 'are', 'you');
$wheels = array();
foreach($cogs as $cog)
{
$wheels[] = array($cog);
}
function recursive($placement){
$counter = count($placement);
$nword = '';
for($i = 0; $i < $counter; $i++) {
$nword .= $placement[$i][0];
echo $nword;
}
recursive($placement);
}
recursive($wheels);
Clearly I am doing something wrong as my function just keeps going. I cant figure out why… I am new to recursive functions in PHP so any help on a solution to this would be appreciated. What is the best way to have a safety net so my PHP function does not run forever for any recursive function?

It doesn't stop because recursive is an infinite loop. You've written:
function recursive($placement) {
// Code that doesn't return, and outputs text
recursive($placement);
}
Why do you expect that to ever terminate?
Any recursive function needs to have some condition that eventually will prove true and upon proving true will terminate the recursion.
Your browser is freezing because it likely is having a hard time with the massive amounts of output your PHP script has sent to it.
Most PHP installations will eventually terminate a script that has run for too long. However, as mentioned, your browser may have difficulties if it has to deal with a huge amount of output from the infinite loop.

Because you don't have a stop condition. In your function you print every time the same things (the first position of each vars in the array) and after that you call again the same function with the same input.

Related

get output 'during' a long foreach loop - not just at the end of last item in loop

i have a long hours working foreach loop which outputs correctly at the end when all items are processed..
foreach ($matches[0] as $map_link) {
if ($map_link!='' && $i < $max_tags ) {
include('reg-process.php');
}
$i++;
}
infact for each $matches[0] which are over 600 matches it includes the
'reg-process.php' page which processes each match in turn and after over one hour it finishes and outputs all results ..
what i need is not to wait till the last item to see results, so while the loop is working after each item is processed it could be echoed..
so again i need every time the loop includes 'reg-process.php' page print out
the result , not to wail up to the last item then all print out at once.. something like continue?
include shouldn't be used in the way you use it, it should be used to include functionality or reduce single file complexity rather than to misuse it as a function. So first of all, get rid of the include as this will lead to problems at some point in time (i.e. you can't include one file multiple times in case it contains functions).
There are different ways to get what you want, here are just two possibilities:
1.) File-based logging:
<?php
// file: register_process.php
function registerProgress($map_link)
{
// YOUR CODE
// ...
// assuming that the result of your code is a string variable that can be logged
file_put_contents('registration.log', $logResult, FILE_APPEND);
}
include('register_progress.php');
foreach ($matches[0] as $map_link) {
if ($map_link!='' && $i < $max_tags ) {
registerProgress($map_link);
}
$i++;
}
2.) Switch to ajax:
in case you are running the script as part of a web application (rather than as console application), you could rewrite your code to execute one page request per map link.
Advantages: you'll get a visible result per executed call, reduced script memory usage, lesser risk of timeouts (due to PHP, webserver or browser timeouts).
Disadvantages: increased page requests and code refactoring required.
ob_flush() will not work as browsers do not parse content of a pending page request; instead you would have to use a network sniffer to read the partial flushed content.
You are not following foreach format with proper syntax. The ideal code are follows-
foreach ($arr as $value) {
$value = $value * 2;
}
Make sure that, $matches[0] is an array. Without array, it will not work. Just rewrite your code, hope will work properly.

how to make a php function loop every 5 seconds

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

Breaking infinite loop of a PHP script running in background [not killing the process]

I have a PHP script which will run 24/7 on a VPS with an infinite loop, but problem is that how can I break the infinite loop in php script when desired in order so that the script exists properly?
I know I can kill the process, but if I kill then script will stop immediately
and my loop size is very big and if at time of killing the process the execution of is somewhere in middle of loop then the rest half of loop would not be executed and it will create bugs. Also I have some code after loop so if process gets killed then that code would not be executed.
So my question is that how to break a infinite loop of a PHP script running in background when desired without killing the process?
Instead of:
while(true) {
Do:
while(!file_exists("KILL")) {
Then, when you want to kill the script, simply create the KILL file. You could make it easier for yourself by having a kill.php script that just creates that file for you, so you don't have to remember exactly what to do.
Personally I find PHP scripts easier to work with over EXEs for console apps, but that's just opinion.
Q1. Windows Task Scheduler.. don't insert any loop, just insert CGI directory,then create time.
Q2. PHP would be alot better if you ask me.
although, It's not about Performance.
Sounds like you're coding a server, take a look at this, hope it helps.
<?php
class ServerManager
{
private $serverState;
public function process()
{
if(!$this->getServerState())
{
return;
}
$this->processNewConnections();
$this->processExistingConnections();
}
public function setServerState($state)
{
$this->serverState = $state;
}
public function getServerState()
{
return $this->serverState;
}
private function processNewConnections()
{
...
}
private function processExistingConnections()
{
...
if(connected client has requested that the server should stop)
{
$this->setServerState(false);
}
...
}
}

Codeigniter LongPolling "while(true)" does not work?

I am currently implementing a long polling function in Codeigniter and have come up a problem.
Lets say I have a normal PHP Controller:
function longpolling()
{
//PHP Timelimit infinite
set_time_limit(0);
while(true){
echo "test";
//Sleep 3 Seconds
sleep(3);
}
}
The page is just saying loading when called and does not return "test" instead you get 404 Error after a while.
What am I doing wrong?
Thank you!
You aren't doing anything 'wrong' it's just that php doesn't work the way you're expecting it to.
If you did it like this:
$i = 0;
while ($i < 10)
{
echo "Hi There!";
sleep(2);
$i++;
}
It will eventually output lots of Hi There, but not one at a time, rather it will all display at the end of the while loop.
You could even throw a flush() in there
$i = 0;
while ($i < 10)
{
echo "Hi There!";
flush();
sleep(2);
$i++;
}
And you still wont get anything until the very end.
Because your while(true) never ends you will never see any output, and I assume the browser timeout kicks in? Or the max_execution_time setting is reached?
Just popped into my head now: It might work if you wrote some data to a file in an infinite loop I have never tried it myself.
I've ran into issues like this myself. You'll have to look into flushing the output out as php and/or the webserver might be buffering the data until a certain threshold is met. I had a horrible time struggling with IIS over this, I think Apache is a lot easier to manage. Plus there's telling the webserver what to do as well. For apache, here's a snippet found on php.net:
I just had some problems with flush() and ob_flush(). What I did to
resolve this problem took me some time to figure out so I'd like to
share what I came up with.
The main problem is the php setting "output_buffering" which can be
set too large and will prevent your text from outputting. To change
this value you can either set it in php.ini or you can add the line
php_value output_buffering "0"
to your .htaccess file. It will not work with ini_set() since it is
PHP_INI_PERDIR.
This is combined with the flush() function used before sleep(). I also had to output over a number of characters before it started flushing properly:
public function longpolling()
{
echo str_repeat(" ", 1024); flush();
for( $i = 0; $i < 10; $i++) {
echo $i."<br/>";
flush();
sleep(1);
}
}
Also. I just tried this on my server and it wouldn't work until I added the php_value line to my htaccess file. Once I did, it worked as expected.
The page will keep loading until the PHP file execution has reached the end of the file. PHP doesn't work like C or C++. You make a request and when everything is done you get the output. Once the page is loaded no PHP is executing anymore.
And sleep() is just used to slow PHP down in some cases. In this case:
echo "Something";
sleep(30);
echo " else";
"Something" and " else" will be printed at the same moment while the total execution will take 30 seconds more.

How to wait for a variable to return before the next function starts

I have a simple function1 that does a http request to a google api and returns the $result.
I then have another function2 that, if $result isset, should use $result to do some computing and then return $finalresult. .
My problem is that the call to the google api takes a couple of seconds and by the time $result is returned by function1, function2 has already returned $finalresult without taking into consideration $result.
What I am looking to do is to have function1 to run completely and return $result before function2 even begins.
Preferrably I am looking for a solution that is not simply using "sleep()" as this function will not guarantee that $result is actually returned. (Unless there is some way to loop a sleep(1) until $return isset, or something like that)
Sample code for the visual gals and guys
function1_geocode($address); // this function makes a http request to google and returns $result
function2_proximitysearch(){
if (isset($result)){
//inevitably by the time the script gets there, $result hasn't been returned yet therefore none of the "some stuff" code is executed.
//some stuff
}
else {
//some other stuff
}
}
PHP is not asynchronous. Functions are executed one after another.
why don't you have function 1 call function 2 when it is done?
additionally, Mchl is right. function 1 will have to complete before the code executes function 2. Maybe you should set up your code like so:
$foo = 0;
$foo = function1();
if($foo > 0)
function2();
function1()
{
if($something)
$foo = 1;
}
function2()
{
$something = $else;
}
That way it will only call function 2 if function 1 changed the value of $foo.
Of you could post your full code and we'll know what you're trying to do.
PHP isn't threaded, so if you call function1_geocode before function2_proximitysearch, $result should always be set.
It could be that function1_geocode($address) has a bug, or else you might be missing some documentation for how that function is used.
It's possible to kinda simulate asynchronous functionality by, for example saving results in a file to be dealt with by a second page load. But that would have to be specifically designed that way. Within one PHP page load, you can't have a process running in the background.

Categories