views:

548

answers:

11

While reading through the great online PHP tutorials of Paul Hudson he said

Perhaps surprisingly, infinite loops can sometimes be helpful in your scripts. As infinite loops never terminate without outside influence, the most popular way to use them is to break out of the loop and/or exit the script entirely from within the loop whenever a condition is matched. You can also rely on user input to terminate the loop - for example, if you are writing a program to accept people typing in data for as long as they want, it just would not work to have the script loop 30,000 times or even 300,000,000 times. Instead, the code should loop forever, constantly accepting user input until the user ends the program by pressing Ctrl-C.

Would you please give me a simple running example of how to use infinite loops in PHP ?

+5  A: 

Monitoring applications

If you have a background process that monitors the state of your servers and sends an email if trouble occurs. It would have an infinite loop to repeatably check the servers (with some pause between iterations.)

Server listening for Clients

If you have a server script that listens to a socket for connections, it will loop infinitely, blocking while waiting for new clients to connect.

Video Games

Games usually have a "game loop" that runs once a frame, indefinitely.

Or... anything else that needs to keep running in the background with periodic checks.

Ben S
Did you see any video game written using PHP language?
Sergey Kuznetsov
@Sergey: Sure, why not? PHP has some graphical libraries. You could write a game in PHP if you wanted to. I mention it because it's a classic example of the infinite loop.
Ben S
@Ben S: Of course, but writing a video game using PHP language is great headache, I think :)
Sergey Kuznetsov
I think PHP is not suitable for real time applications. But I read once that if you want to use it, nothing can stop you !
ta.abouzeid
+4  A: 

If you implemented a socket server (taken from: http://devzone.zend.com/article/1086 ):

    #!/usr/local/bin/php –q

<?php
// Set time limit to indefinite execution
set_time_limit (0);

// Set the ip and port we will listen on
$address = '192.168.0.100';
$port = 9000;
$max_clients = 10;

// Array that will hold client information
$clients = Array();

// Create a TCP Stream socket
$sock = socket_create(AF_INET, SOCK_STREAM, 0);
// Bind the socket to an address/port
socket_bind($sock, $address, $port) or die('Could not bind to address');
// Start listening for connections
socket_listen($sock);

// Loop continuously
while (true) {
    // Setup clients listen socket for reading
    $read[0] = $sock;
    for ($i = 0; $i < $max_clients; $i++)
    {
        if ($client[$i]['sock']  != null)
            $read[$i + 1] = $client[$i]['sock'] ;
    }
    // Set up a blocking call to socket_select()
    $ready = socket_select($read,null,null,null);
    /* if a new connection is being made add it to the client array */
    if (in_array($sock, $read)) {
        for ($i = 0; $i < $max_clients; $i++)
        {
            if ($client[$i]['sock'] == null) {
                $client[$i]['sock'] = socket_accept($sock);
                break;
            }
            elseif ($i == $max_clients - 1)
                print ("too many clients")
        }
        if (--$ready <= 0)
            continue;
    } // end if in_array

    // If a client is trying to write - handle it now
    for ($i = 0; $i < $max_clients; $i++) // for each client
    {
        if (in_array($client[$i]['sock'] , $read))
        {
            $input = socket_read($client[$i]['sock'] , 1024);
            if ($input == null) {
                // Zero length string meaning disconnected
                unset($client[$i]);
            }
            $n = trim($input);
            if ($input == 'exit') {
                // requested disconnect
                socket_close($client[$i]['sock']);
            } elseif ($input) {
                // strip white spaces and write back to user
                $output = ereg_replace("[ \t\n\r]","",$input).chr(0);
                socket_write($client[$i]['sock'],$output);
            }
        } else {
            // Close the socket
            socket_close($client[$i]['sock']);
            unset($client[$i]);
        }
    }
} // end while
// Close the master sockets
socket_close($sock);
?>
AJ
A: 

I'm thinking about the guess-the-number game, where the user has to guess the randomly (or not) generated number, so, he'll have to enter numbers until he gets it. Is that what you needed ?

Soufiane Hassou
+3  A: 

Maybe it useful when you write a command line PHP application? Because when PHP-scripts runs by web-server (Apache or any other) they lifetime is limited by 30 seconds by default (or you can manually change this limit at the configuration file).

Sergey Kuznetsov
Yeah I'm also curious how one would let it go infinate with a hard lifetime limit of 30 sec etc (in php.ini)
Jakub
A: 

Paul Biggar has posted a make script for LaTeX projects which uses an infinite loop to run in the background and continually tries to rebuild the LaTeX sources.

The only way to terminate the script is to kill it externally (e.g. using Ctrl+C).

(Granted, not PHP (Bash, actually) but the same script could well be implemented in PHP instead.)

Konrad Rudolph
A: 

For user input...

while True:
    input = get_input_from_user("Do you want to continue? ")
    if input not in ("yes", "y", "no", "n"):
        print "invalid input!"
    else: 
        break
gahooa
What happens when stdin is closed? Infinite loops are very dangerous...
Daniel Papasian
If stdin is closed, you get an exception: `ValueError: I/O operation on closed file`.
Jason Orendorff
A: 

Sometimes instead of a loop which would have an exit condition too long to preserve readability an improperly named "infinite" loop may be the best way to go.

<?php

while(1) {
  // ... 
  $ok=preg_match_all('/.../',$M,PREG_SET_ORDER);
  if (!$ok) break;

  switch(...) { ... }

  // match another pattern
  $ok=preg_match('/.../',$M,PREG_SET_ORDER);
  if (!$ok) break;

  //and on, and on...
}
ZJR
It's something you cannot avoid to do in python, but the loop isn't really intended not to end.
ZJR
sometimes a `do { ... } while($condition);` will be a better fit
ZJR
+2  A: 

I'm going to disagree with the other answers so far, and suggest that, if you're being careful about things, they never have a place.

There is always some condition in which you want to shut down, so at the very least, it should be while(test if shutdown not requested) or while(still able to meaningfully run)

I think practically there are times when people don't use the condition and rely on things like sigint to php to terminate, but this is not best practice in my opinion, even if it works.

The risk of putting the test inside the loop and breaking if it fails is that it makes it easier for the code to be modified in the future to inadvertently create an endless loop. For example, you might wrap the contents of the while loop inside another loop, and then all of a sudden the break statement doesn't get you out of the while...

for(;;) or while(1) should be avoided whenever possible, and it's almost always possible.

Daniel Papasian
A: 

I think a point is being missed... there aren't really infinite loops (you would be stuck in them forever), rather while(true){...} and co are useful when you have non trivial exit conditions (e.g. those coming from a third-party library, or a limit which would take a lot of time to calculate but can be worked out incrementally inside of the loop, or something relying on user input).

It shouldn't be surprising that not every loop can be concisely stated as a for, while or do loop without using break.

jheriko
A: 

Infinite loops are particulary useful when creating command line applications. The application will then run until the user tells it to stop. (add a break/exit-statement when the user input is "quit", for instance)

while (true) {
  $input = read_input_from_stdin();

  do_something_with_input();

  if ($input == 'quit') {
    exit(0);
  }
}
Hanse
A: 

Infinite loops are one of those tools you keep in a separate toolbox that doesn't get opened much as it is a tool of (almost) last resort.

The best use I have found for them is with state machines or loops that are approaching state machines. This is because the exit condition is usually quite complex and cannot be put at the top or the bottom of the loop.

staticsan