Когда бесконечные циклы полезны в PHP?

Прочитав великолепные онлайн-уроки PHP Пола Хадсона, он сказал:

Возможно, удивительно, что бесконечные циклы иногда могут быть полезны в ваших сценариях. Поскольку бесконечные циклы никогда не заканчиваются без внешнего влияния, самым популярным способом их использования является выход из цикла и / или выход из сценария целиком изнутри цикла всякий раз, когда выполняется условие. Вы также можете полагаться на ввод пользователя для завершения цикла – например, если вы пишете программу, чтобы принимать людей, печатающих данные до тех пор, пока они этого хотят, просто не получится, чтобы цикл сценария составлял 30 000 раз или даже 300 000 000 раз , Вместо этого код должен зацикливаться навсегда, постоянно принимая ввод пользователя, пока пользователь не закончит программу, нажав Ctrl-C.

Не могли бы вы дать мне простой пример использования бесконечных циклов в PHP?

Мониторинг приложений

Если у вас есть фоновый процесс, который отслеживает состояние ваших серверов и отправляет электронное сообщение, если возникают проблемы. У него будет бесконечный цикл для повторной проверки серверов (с некоторой паузой между итерациями).

Сервер, слушающий клиентов

Если у вас есть серверный скрипт, который слушает сокет для подключений, он будет циклически работать бесконечно, блокируя при ожидании подключения новых клиентов.

Видео игры

Игры обычно имеют «игровой цикл», который работает один раз в кадре, на неопределенный срок.

Или … что-нибудь еще, что нужно продолжать работать в фоновом режиме с периодическими проверками.

Если вы реализовали сервер сокетов (взято из: 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); ?> 

Может быть, это полезно, когда вы пишете приложение PHP из командной строки? Потому что, когда PHP-скрипты запускаются с помощью веб-сервера (Apache или любого другого), время жизни ограничено на 30 секунд по умолчанию (или вы можете вручную изменить этот предел в файле конфигурации).

Я пока не соглашусь с другими ответами и предположим, что, если вы будете осторожны в делах, у них никогда не будет места.

Всегда есть какое-то условие, в котором вы хотите закрыть, так что, по крайней мере, оно должно быть пока ( проверьте, не выключено ли выключение ) или пока ( все еще можно осмысленно запустить )

Я думаю, что практически есть моменты, когда люди не используют условие и полагаются на такие вещи, как sigint, на php, чтобы закончить, но это не лучшая практика, на мой взгляд, даже если она работает.

Риск сдачи теста внутри цикла и взлома, если он терпит неудачу, заключается в том, что он облегчает изменение кода в будущем, чтобы непреднамеренно создать бесконечный цикл. Например, вы можете обернуть содержимое цикла while внутри другого цикла, а затем внезапно оператор break не избавит вас от времени …

для (;;) или while (1) следует избегать, когда это возможно, и это почти всегда возможно.

Существует множество способов использования бесконечных циклов, вот пример бесконечного цикла, чтобы получить 100 случайных чисел от 1 до 200

 $numbers = array(); $amount = 100; while(1) { $number = rand(1, 200); if ( !in_array($number, $numbers) ) { $numbers[] = $number; if ( count($numbers) == $amount ) { break; } } } print_r($numbers); 

Бесконечные петли особенно полезны при создании приложений командной строки. Затем приложение будет запускаться до тех пор, пока пользователь не остановит его. (добавьте оператор break / exit-statement, когда пользовательский ввод «quit», например)

 while (true) { $input = read_input_from_stdin(); do_something_with_input(); if ($input == 'quit') { exit(0); } } 

Я думаю о игре с угадыванием номера, где пользователь должен угадать произвольно (или нет) сгенерированный номер, поэтому ему придется вводить цифры, пока он не получит его. Это то, что вам нужно?

Пол Биггар опубликовал сценарий make для проектов LaTeX, который использует бесконечный цикл для запуска в фоновом режиме и постоянно пытается перестроить источники LaTeX.

Единственный способ остановить скрипт – убить его извне (например, с помощью Ctrl + C ).

(Конечно, не PHP (Bash, на самом деле), но тот же скрипт может быть реализован в PHP вместо этого.)

Для ввода пользователем …

 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 

Иногда вместо цикла, который слишком долго имел бы условие выхода, чтобы сохранить читаемость, может быть наилучшим способом использовать ненаправленный «бесконечный» цикл .

 <?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... } 

Я думаю, что точка пропускается … нет бесконечных циклов (вы бы застряли в них навсегда), а while(true){...} и co полезны, когда у вас есть нетривиальные условия выхода (например, те, которые поступают из сторонней библиотеки, или лимит, который занимает много времени для расчета, но может быть постепенно изменен внутри цикла или что-то, что полагается на ввод пользователя).

Не удивительно, что не каждый цикл можно кратко сформулировать как цикл for , while или do без использования break .

Бесконечные петли – один из тех инструментов, которые вы держите в отдельном ящике инструментов, который не открывается, поскольку он является инструментом (почти) последней инстанции.

Лучшее использование, которое я нашел для них, – это государственные машины или циклы, которые приближаются к государственным машинам. Это связано с тем, что условие выхода обычно довольно сложно и не может быть помещено в верхнюю или нижнюю часть цикла.