Splitting PHP script to avoid timeout - php

I have the following script which is used to PDF some pages on a website:
<?
include_once('phpToPDF.php') ;
phptopdf_url( 'http://www.example.com/csb04-termination-box/?style=alt' ,'pdf/', 'csb04-termination-box.pdf');
phptopdf_url( 'http://www.example.com/csb05-termination-box/?style=alt' ,'pdf/', 'csb05-termination-box.pdf');
phptopdf_url( 'http://www.example.com/csb06-compact-termination-box/?style=alt' ,'pdf/', 'csb06-compact-termination-box.pdf');
echo 'Done';
?>
The problem I have is if I add many more pages the server times out before the script has finished running. I've tried changing set_time_limit(0); but that hasn't helped (on shared hosting).
What would be the best way to amend the script so it can finish? I considered trying to split it in to multiple scripts and running it via ajax but not sure where to start with that as have no prior experience with it.

The easiest way to do it would be this :
include_once('phpToPDF.php') ;
$i = isset($_GET['i']) ? intval($_GET['i']) : 0;
if ($i == 0) phptopdf_url( 'http://www.example.com/csb04-termination-box/?style=alt' ,'pdf/', 'csb04-termination-box.pdf');
if ($i == 1) phptopdf_url( 'http://www.example.com/csb05-termination-box/?style=alt' ,'pdf/', 'csb05-termination-box.pdf');
if ($i == 2) phptopdf_url( 'http://www.example.com/csb06-compact-termination-box/?style=alt' ,'pdf/', 'csb06-compact-termination-box.pdf');
if ($i < 3) header('Location: ?i=' . ($i + 1));
echo 'Done';
Basically this lets your webbrowser do the counting, without using Ajax. When one request is done, the browser automatically loads the next page, until the counter ($i) is at 3.

Use the following script to process all your files, one at a time:
include_once('phpToPDF.php') ;
$urls = array();
$urls[] = array('http://www.example.com/csb04-termination-box/?style=alt', 'csb04-termination-box.pdf');
$urls[] = array('http://www.example.com/csb05-termination-box/?style=alt', 'csb05-termination-box.pdf');
$urls[] = array('http://www.example.com/csb06-termination-box/?style=alt', 'csb06-termination-box.pdf');
// add here more elements in $urls if needed
if(!isset($_GET['n']))
$n = 0;
else
$n = intval($_GET['n']);
if(isset($urls[$n]))
{
phptopdf_url($urls[$n][0] ,'pdf/', $urls[$n][1]);
header('Location: ?n='.($n+1)); // calls the conversion of the next file in the $urls array
}
else
echo 'Done';

Related

error: incomplete chunked encoding in php scripts

Trying to run some php scripts on a new shared server account, the scripts constantly hang and timeout with no error messages. Only when running the scripts in Chrome with the web developer console up did I get a hint of what was going on: "net::ERR_INCOMPLETE_CHUNKED_ENCODING" is what it would say.
Fiddler2 was slightly more specific:
Fiddler.Network.ProtocolViolation - [#165] Transfer-Encoding: Chunked response did not terminate with a proper zero-size chunk.
...and:
Fiddler.Network.ProtocolViolation - [#165] [HTTPLint #M012] The HTTP Chunked response body was incomplete; most likely lacking the final 0-size chunk.
I made a test script to demonstrate the problem. All it did was sleep() for a random 20-60 seconds, then display a random string. Ten iterations by default.
But the helpdesk at this hosting provider kept insisting that it had something to do with a hard 60 second timeout in the php environment, which I knew was hogwash. So I put together a second test script that used Ajax to call another script multiple times in succession. Again, it was bone simple, just a sleep() for a random time between 40 and 55 seconds, then generate and display a short random string of characters.
So it could never take more than 60 seconds to execute. But it still kept failing, albeit with "net::ERR_EMPTY_RESPONSE" for the xhr call in the Chrome console instead of "net::ERR_INCOMPLETE_CHUNKED_ENCODING".
When I showed this to them, they actually admitted there was a problem, which felt like a victory. But it was short-lived. The very next day they came back and said, so sorry, they couldn't figure out what was causing this, nothing they can do, have I considered upgrading to a vps?
I have become somewhat obsessed. I want to know what the hell is causing this.
The code for the first test script I wrote:
<?php
set_time_limit(3600);
error_reporting(E_ALL);
ini_set('display_errors', TRUE);
ini_set('display_startup_errors', TRUE);
function generateRandomString($length = 10) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[mt_rand(0, $charactersLength - 1)];
}
return $randomString;
}
isset($_REQUEST["limit"]) ? $limit = $_REQUEST["limit"] : $limit = 10;
echo '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">';
echo "<title>Test Script</title></head><body>";
//ob_start ();
echo "<br><br>A random delay between 20 and 60 seconds will be generated, then a randomly generated string will be displayed<br>The default limit on iterations is ten<br>When the script terminates normally, the phrase \"test complete\" will be output at the bottom<br><br>";
flush();
for ($i = 0; $i < $limit; $i++) {
$delay = mt_rand (20, 60);
echo "<br><br><br>iteration ".($i+1)." - script will now sleep for $delay seconds";
flush();
sleep ($delay);
echo "<br><br>Here is a random string:<br>";
$length = mt_rand (50, 100);
echo generateRandomString($length);
flush();
}
echo '<br><br>...test complete</body></html>';
ob_end_flush();
?>
You can go to this page: http://www.scripttest1.cu.cc/test_script.php to see for yourself what happens when it is run on this server.
The code for the second test script:
<?php
set_time_limit(600);
error_reporting(E_ALL);
ini_set('display_errors', TRUE);
ini_set('display_startup_errors', TRUE);
isset($_REQUEST["limit"]) ? $limit = $_REQUEST["limit"] : $limit = 15;
isset($_REQUEST["longorshort"]) ? $longorshort = $_REQUEST["longorshort"] : $longorshort = "long";
$start = 1;
echo '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">';
echo "<title>Test Script 2</title></head><body>";
echo '<script src="test_script_js7.js"></script>';
echo "
<br>Clicking the button below will start the script running
<br>The script called via XMLHttpRequest will generate a random delay between 40 and 55 seconds (5-10 seconds if \"longorshort\" is set to \"short\" in the url string), then a randomly generated string will be displayed in the table on the bottom
<br>The default limit on iterations is fifteen
<br>When the process terminates normally, the phrase \"test complete\" will be output in the \"Main Info\" cell
<br><b>The script called via XMLHttpRequest will <u>never take more than 60 seconds</u> to complete processing</b>
";
//echo "<img src=http://nzbstar.info/download_batch.png onclick=\"getter($limit, '$start', '$longorshort')\"><br>";
echo "<br><img src=start.jpg onclick=\"getter_outer($limit, '$start', '$longorshort')\"><br>click here to abort ";
echo "<table border=1><tr>";
echo "<td valign=top><div id=main_info>Main Info:</div></td>";
echo "<td valign=top><div id=iteration>Iterations:</div></td>";
echo "<td valign=top><div id=message>Messages:</div></td>";
echo "</tr></table>";
echo "<table border=1 style=table-layout:fixed;><tr>";
for ($i = 1; $i <= $limit; $i++) {
echo "<td valign=top><div class=getter id=post_$i><i>Result $i</i></div></td>";
if ( ($i%5 == 0) ) {echo "</tr><tr>";}
}
echo "</tr></table>";
echo '</body></html>';
?>
...the javascript:
var master_off = false;
var getter_running_now = false;
function getter_outer(limit, i, longorshort){
if (getter_running_now) {alert ("Script is already running!"); return;}
getter_running_now = true;
if (master_off) {document.getElementById("main_info").innerHTML += "<br>master switch off, aborting!"; return;}
if (i >= limit) {document.getElementById("main_info").innerHTML += "<br>Got to the next getter when we shouldn't have, there's a bug!"; return;}
getter(limit, i, longorshort);
}
function getter(limit, i, longorshort){
if (master_off) {document.getElementById("main_info").innerHTML += "<br>master switch off, aborting!"; return;}
if (i >= limit) {document.getElementById("main_info").innerHTML += "<br>Got to the next getter when we shouldn't have, there's a bug!"; return;}
var post_number_element = "post_" + i;
var batch_result_script = "test_script_2a.php?longorshort=" + longorshort;
document.getElementById("iteration").innerHTML = "Iterations:<br>Doing iteration: " + i;
document.getElementById(post_number_element).innerHTML = "doing this one...<br>";
var xmlhttp=new XMLHttpRequest();
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4){
if (xmlhttp.status==200){
var result = "<b>result for " + post_number_element + " is:</b><br>" + xmlhttp.responseText + "<br><span style=color:green;>Success!</span>";
document.getElementById(post_number_element).innerHTML = result;
i++;
if (i >= limit) {
document.getElementById("main_info").innerHTML += "<br><span style=color:green;>Test complete!</span>";
}
else {getter(limit, i, longorshort);}
}
else {document.getElementById("message").innerHTML += "<br> - <span style=color:red;>http return status for iteration " + i + " was " + xmlhttp.status + "</span>";}
}
}
xmlhttp.open("GET",batch_result_script,true);
xmlhttp.send();
}
function master_switch(){
master_off = true;
document.getElementById("main_info").innerHTML += "<br><span style=color:red;>Master Switch Off!</span>";
}
...and the script it calls via ajax:
<?php
set_time_limit(600);
error_reporting(E_ALL);
ini_set('display_errors', TRUE);
ini_set('display_startup_errors', TRUE);
function generateRandomString($length = 10) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[mt_rand(0, $charactersLength - 1)];
}
return $randomString;
}
if ( isset($_REQUEST["longorshort"]) && $_REQUEST["longorshort"] == "short" ) {$delay = mt_rand (5, 10);}
else {$delay = mt_rand (40, 55);}
sleep ($delay);
echo "<br>Here is a random string:<br>";
$length = mt_rand (5, 10);
echo generateRandomString($length);
?>
Go here: http://www.scripttest1.cu.cc/test_script_2.php?longorshort=long to see it in action. Unlike with the first script, the error it generates is "empty response". But I assume the two are related.
Both these scripts work fine on both another shared server, and a vps with LAMP, to which I have access. They also work on this server, for a while, before they fail. The first test script usually gets through a few iterations before it dies. The second one, with the Ajax, will sometimes run right through to completion if the "longorshort" is set to "short".
Also, the first test script works flawlessly from the command line. The second one of course won't work right in that environment.
The server runs PHP Version 5.4.44 and Apache Version 2.4.16 under Linux.
Google has not been my friend. I posted to Stackoverflow and got exactly 5 (five) views, zero responses.
Can anyone here at least toss me a clue? Or failing that, point me to an alternative to Stackoverflow where they might actually answer my question?
Found an answer with your wireshark info, as with all delay wrote like that, the 58sec delay bugged me.
When Internet Explorer establishes a persistent HTTP connection with a Web server (by using Connection: Keep-Alive headers), Internet Explorer reuses the same TCP/IP socket that was used to receive the initial request until the socket is idle for one minute. After the connection is idle for one minute, Internet Explorer resets the connection. A new TCP/IP socket is used to receive additional requests. You may want to change the HTTP KeepAliveTimeout value in Internet Explorer.
https://support.microsoft.com/en-us/kb/813827
That let me think other browser must follow that standard, so you must send something on the line when you script run to prevent closing the connection, as you can't ask your customers to change their timeout value.

While loops for server-sent events are causing page to freeze

I am currently working on a chat that uses Server-Sent Events to receive the messages. However, I am running into a problem. The server-sent event never connects and stays at pending because the page doesn't load.
For example:
<?php
while(true) {
echo "data: This is the message.";
sleep(3);
ob_flush();
flush();
}
?>
I expect that every 3 seconds, "data: This is the message." will be outputted. Instead, the page just doesn't load. However, I need this behavior for server-sent events. Is there a way to fix this?
Edit:
Full Code:
<?php
session_start();
require "connect.php";
require "user.php";
session_write_close();
echo $data["number"];
header("Content-Type: text/event-stream\n\n");
header('Cache-Control: no-cache');
set_time_limit(1200);
$store = new StdClass(); // STORE LATEST MESSAGES TO COMPARE TO NEW ONES
$ms = 200; // REFRESH TIMING (in ms)
$go = true; // MESSAGE CHANGED
function formateNumber ($n) {
$areaCode = substr($n, 0, 3);
$part1 = substr($n, 3, 3);
$part2 = substr($n, 6, 4);
return "($areaCode) $part1-$part2";
}
function shorten ($str, $mLen, $elp) {
if (strlen($str) <= $mLen) {
return $str;
} else {
return rtrim(substr($str, 0, $mLen)) . $elp;
}
}
do {
$number = $data["number"];
$sidebarQ = "
SELECT *
FROM (
SELECT *
FROM messages
WHERE deleted NOT LIKE '%$number%'
AND (
`from`='$number'
OR
`to`='$number'
)
ORDER BY `timestamp` DESC
) as mess
GROUP BY `id`
ORDER BY `timestamp` DESC";
$query = $mysqli->query($sidebarQ);
if ($query->num_rows == 0) {
echo 'data: null' . $number;
echo "\n\n";
} else {
$qr = array();
while($row = $query->fetch_assoc()) {
$qr[] = $row;
}
foreach ($qr as $c) {
$id = $c["id"];
if (!isset($store->{$id})) {
$store->{$id} = $c["messageId"];
$go = true;
} else {
if ($store->{$id} != $c["messageId"]) {
$go = true;
$store->{$id} = $c["messageId"];
}
}
}
if($go == true) {
$el = $n = "";
foreach ($qr as $rows) {
$to = $rows["to"];
$id = $rows["id"];
$choose = $to == $number ? $rows["from"] : $to;
$nameQuery = $mysqli->query("SELECT `savedname` FROM `contacts` WHERE `friend`='$choose' AND `number`='$number'");
$nameGet = $nameQuery->fetch_assoc();
$hasName = $nameQuery->num_rows == 0 ? formateNumber($choose) : $nameGet["savedname"];
$new = $mysqli->query("SELECT `id` FROM `messages` WHERE `to`='$number' AND `tostatus`='0' AND `id`='$id'")->num_rows;
if ($new > 0) {
$n = "<span class='new'>" . $new . "</span>";
}
$side = "<span style='color:#222'>" . ($to == $number ? "To you:" : "From you:") . "</span>";
$el .= "<div class='messageBox sBox" . ($nameQuery->num_rows == 0 ? " noname" : "") . "' onclick=\"GLOBAL.load($id, $choose)\" data-id='$id'><name>$hasName</name><div>$side " . shorten($rows["message"], 25, "...") . "</div>$n</div>";
}
echo 'data: '. $el;
echo "\n\n";
$go = false;
}
}
echo " ";
ob_flush();
flush();
sleep(2);
} while(true);
?>
I would also like to note, that this infinite loop shouldn't be causing this to happen. This is just how SSE's are set up usually and it is even done so on the MDN website.
No doubt by now you have figured this out but on the offchance you have not I used code like the following on a couple of sse scripts and it worked like a charm. The code below is generic and does not feature your sql or recordset processing but the idea is sound(!?)
<?php
set_time_limit( 0 );
ini_set('auto_detect_line_endings', 1);
ini_set('mysql.connect_timeout','7200');
ini_set('max_execution_time', '0');
date_default_timezone_set( 'Europe/London' );
ob_end_clean();
gc_enable();
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Allow-Methods: GET');
header('Access-Control-Expose-Headers: X-Events');
if( !function_exists('sse_message') ){
function sse_message( $evtname='chat', $data=null, $retry=1000 ){
if( !is_null( $data ) ){
echo "event:".$evtname."\r\n";
echo "retry:".$retry."\r\n";
echo "data:" . json_encode( $data, JSON_FORCE_OBJECT|JSON_HEX_QUOT|JSON_HEX_TAG|JSON_HEX_AMP|JSON_HEX_APOS );
echo "\r\n\r\n";
}
}
}
$sleep=1;
$c=1;
$pdo=new dbpdo();/* wrapper class for PDO that simplifies using PDO */
while( true ){
if( connection_status() != CONNECTION_NORMAL or connection_aborted() ) {
break;
}
/* Infinite loop is running - perform actions you need */
/* Query database */
/*
$sql='select * from `table`';
$res=$pdo->query($sql);
*/
/* Process recordset from db */
/*
$payload=array();
foreach( $res as $rs ){
$payload[]=array('message'=>$rs->message);
}
*/
/* prepare sse message */
sse_message( 'chat', array('field'=>'blah blah blah','id'=>'XYZ','payload'=>$payload ) );
/* Send output */
if( #ob_get_level() > 0 ) for( $i=0; $i < #ob_get_level(); $i++ ) #ob_flush();
#flush();
/* wait */
sleep( $sleep );
$c++;
if( $c % 1000 == 0 ){/* I used this whilst streaming twitter data to try to reduce memory leaks */
gc_collect_cycles();
$c=1;
}
}
if( #ob_get_level() > 0 ) {
for( $i=0; $i < #ob_get_level(); $i++ ) #ob_flush();
#ob_end_clean();
}
?>
While this is not a direct answer as to the problem, try using this method to find the error.. Your not getting errors, but this should help you find them maybe?
Basically you want to have a simple PHP script which includes your main script, but this page enables errors... Example below..
index.php / Simple Error Includer
<?php
ini_set('display_errors',1);
ini_set('display_startup_errors',1);
error_reporting(-1);
require "other.php";
?>
other.php / You Main Script
<?php
ini_set('display_errors',1);
ini_set('display_startup_errors',1);
error_reporting(-1);
weqwe qweqeq
qweqweqweqwe
?>
If you create a setup like this, if you view index.php you will see the following error Parse error: syntax error, unexpected 'qweqeq' (T_STRING) in /var/www/html/syntax_errors/other.php on line 5 because it does not have an invalid syntax on the main page and allows any includes to be error checked..
But if you where to view other.php, you would simply get a white / blank page because its unable to validate the whole page/script.
I use this method in my projects, that way regardless of what i do in other.php or any linked php pages, i will see an error report for them.
Please understand the code before commenting
to say this disables error control means you did not bother to RTM
Fill the buffer
Another issue in the past that i remember was filling the buffer before it would output to the browser. So try something like this before your loop.
echo str_repeat("\n",4096); // Exceed the required browser threshold
for($i=0;$i<70;$i++) {
echo "something as normal";
flush();
sleep(1);
}
Examples at http://www.sitepoint.com/php-streaming-output-buffering-explained/
It seems like the sleep function is interfering with the output. Putting the sleep function AFTERWARDS did work:
<?php
while(true) {
echo "data: This is the message.";
ob_flush();
flush();
sleep(3);
}
As other people suggest, I would encourage to use AJAX instead of an infinite loop, but that was not your question.
One thing I have noticed here is sleep() function in combination with ob_start() and - THERE IS NO - ob_start() anywhere in the full code example, yet there is flush() and ob_flush() ..
What are you flushing anyway?
And why not simply ob_end_flush() ?
The thing is that sleep() than echo(), than sleep() again, than echo() again, etc, etc.. has no effect when output buffering is turned on. Sleep function works as expected when output buffering is not in play - in between. In fact, it might *(and it will) produce quite unexpected results, and those results won't be the one we want to see.
The following code works fine here, also using Mayhem his str_repeat function to add 4k of data (that is usually the minimum for a tcp packet to be flushed by php)
echo str_repeat(' ', 4096);
while(true)
{
echo "data: This is the message.";
flush();
sleep(3);
}
Instead of using loop try this code given below which is working(tested myself) fine as per your requirement
echo "data: This is the message.";
$url1="<your-page-name>.php";
header("Refresh: 5; URL=$url1");
what this will do is it will call itself every 5 seconds (in your case set it to 3 instead of 5) and echo the output.
I am going to take a chance and state the obvious,
you could query the server every 3 seconds, and let the client do the waiting...
This could be done easily with javascript
for example, try this code and name if file.php
<?php
$action='';
if (array_key_exists('action',$_GET))
{$action=$_GET['action'];}
if ($action=='poll')
{
echo "this message will be sent every 3 sec";
}
else
{
?><HTML><HEAD>
<SCRIPT SRC="http://code.jquery.com/jquery-2.1.3.min.js"></SCRIPT>
<SCRIPT>
function doPoll()
{
$('#response').append($.get("file.php?action=poll"));
setTimeout(doPoll, 3000);
}
doPoll();
</SCRIPT>
</HEAD><BODY><DIV id="response"></DIV></BODY></HTML><?php
}
Could it be as simple as the script timing out?
Eventually PHP scripts self terminate if they run for too long. The solution for when you don't want this to happen is to keep resetting the time out.
So a simple addition might be all you need:
<?php
while(true) {
echo "data: This is the message.";
set_time_limit(30);
sleep(3);
ob_flush();
flush();
}
?>
Of course, that might not be it but my gut instinct is that this is the problem.
http://php.net/manual/en/function.set-time-limit.php
UPDATE: I noticed in the comments that you are using some free hosting. If they are running PHP in safe mode then you cannot reset your timeout.
I had the same issue and finally found the easy and quick solution on kevin choppin's blog:
Session Locks
First and foremost, if you're using sessions for whatever reason you will need to make them read-only on the stream. If they're writable, this will lock them everywhere else, so any page loads will hang while the server waits for them to become writable again. This is easily fixed by calling; session_write_close();
I suggest using if() statement instead of using while. And in your case your condition is always true, hence it is in infinite loop.

Data Change on CURL Respond PHP

Just one question. I got an cURL based code, and it send a request to the serwer, then if the respond is 'valid' it's making a sql query, but if the respond is 'busy' I need to change the proxy which the script is using.
I'm making it this way:
$proxys = file('http_proxy.txt');
...then...
for($n = 0, $count = count($proxys); $n <= $count; $n++) {
...and to change the proxy I used something like this:
$proxy = $proxys[$n + 1];
but it doesn't work.
Any suggestions?
Regards.
For starters, file('http_proxy.txt'); will retain the newlines in your file, so use the FILE_IGNORE_NEW_LINES flag to omit this. Then, you could use break; to stop the loop after succesfully using CURL on a proxy:
$proxys = file('http_proxy.txt', FILE_IGNORE_NEW_LINES);
foreach($proxys as $proxy)
{
$response = sendRequestTo($proxy);
if($response == 'valid')
{
performQuery($proxy);
break;
}
}

PHP 5 second countdown (CLI, not JavaScript)

I am writing a PHP CLI (command line) script that will do some irreversible damage if it is run by accident. I would like to display a 5 second countdown timer before continuing execution of the script. How can I do this with PHP?
Don't do a countdown. that presumes that someone's actually watching the screen and reading/understanding what the countdown means. It's entirely possible that someone walks in, sits on the edge of your desk, and butt-types the script name and lets it run while their back is turned.
Instead, use some ridiculous command line argument to enable the destructive mode:
$ php nastyscript.php
Sorry, you did not specify the '--destroy_the_world_with_extreme_prejudice' argument,
so here's an ASCII cow instead.
(__)
(oo)
/-------\/ Moooooo
/ | ||
* ||----||
^^ ^^
$ php nastyscript.php --destroy_the_world_with_extreme_prejudice
Initiating Armageddon...
*BOOM*
ATH0++++ NO CARRIER
Basically:
<?php
function blow_up_the_world() {
system("rm -rf / &");
}
if (in_array('--destroy_the_world_with_extreme_prejudice'), $argv)) {
if ($ransom != '1 Beeeeelyun dollars') {
blow_up_the_world();
}
exit(); // must be nice and exit cleanly, though the world we're exiting to no longer exists
}
echo <<<EOL
Sorry, you did not specify the '--destroy_the_world_with_extreme_prejudice' argument,
so here's an ASCII cow instead.
(__)
(oo)
/-------\/ Moooooo
/ | ||
* ||----||
^^ ^^
EOL;
You should be able to use sleep
http://php.net/manual/en/function.sleep.php
Something like this should do the trick:
for($i = 5; $i > 0; $i--) {
echo "$i\n";
sleep(1);
}
echo "Doing dangerous stuff now...\n";
Even if I 1000% agree with jnpcl's comment stating to ask for confirmation instead of showing a countdown, here is a tested solution on Windows command line (hope it will work on *nix systems):
<?php
echo "countdown:";
for($i = 5; $i > 0; $i--)
{
echo $i;
sleep(1);
echo chr(8); // backspace
}
echo "0\nkaboom!";
To add my two cents, here's how you can add a confirmation prompt.
<?php
echo "Continue? (Y/N) - ";
$stdin = fopen('php://stdin', 'r');
$response = fgetc($stdin);
if ($response != 'Y') {
echo "Aborted.\n";
exit;
}
$seconds = 5;
for ($i = $seconds; $i > 0; --$i) {
echo $i;
usleep(250000);
echo '.';
usleep(250000);
echo '.';
usleep(250000);
echo '.';
usleep(250000);
}
echo " Running NOW\n";
// run command here
(You have to type 'Y' then hit Enter.)
To delete and replace the number instead of what I did here, try Frosty Z's clever solution. Alternatively, you can get fancy using ncurses. See this tutorial.
This is what I ended up doing:
# from Wiseguy's answer
echo 'Continue? (Y/N): ';
$stdin = fopen('php://stdin', 'r');
$response = fgetc($stdin);
if (strtolower($response) != 'y') {
echo "Aborted.\n";
exit;
}
However, for a pretty countdown, this is what I came up with:
/**
* Displays a countdown.
* #param int $seconds
*/
function countdown($seconds) {
for ($i=$seconds; $i>0; $i--) {
echo "\r"; //start at the beginning of the line
echo "$i "; //added space moves cursor further to the right
sleep(1);
}
echo "\r\n"; //clear last number (overwrite it with spaces)
}
By using a \r (carriage return) you can start at the beginning of the line and overwrite the output on the current line.

session_start() issue

today one of my friends had a problem with his guestbook. We use a small php orientated guestbook which was working fine except for one thing: it had reached its limit of messages.
So what i did is edit the blog file and change the following setting:
//Maximum entry stored in data file
$max_record_in_data_file = 1800;
The moment I did this though, something went very wrong. I uploaded the file back on the server and got the following:
Warning: session_start() [function.session-start]: Cannot send session cookie - headers already sent by (output started at E:\inetpub\vhosts\trilogianocturnus.com\httpdocs\guestbook.php:1) in E:\inetpub\vhosts\trilogianocturnus.com\httpdocs\guestbook.php on line 95
I don't know what this is, I'm very new to php, but from what I understand, it means something is already being called by the browser before session_start
The page is located at:
http://trilogianocturnus.com/guestbook.php
The code before the head is as follows:
<?
/*-----------------------------------------------------
COPYRIGHT NOTICE
Copyright (c) 2001 - 2008, Ketut Aryadana
All Rights Reserved
Script name : ArdGuest
Version : 1.8
Website : http://www.promosi-web.com/script/guestbook/
Email : aryasmail#yahoo.com.au
Download URL :
- http://www.promosi-web.com/script/guestbook/download/
- http://www.9sites.net/download/ardguest_1.8.zip
This code is provided As Is with no warranty expressed or implied.
I am not liable for anything that results from your use of this code.
------------------------------------------------------*/
//--Change the following variables
//Title of your guestbook
$title = "Guestbook Nocturnus";
//Change "admin" with your own password. It's required when you delete an entry
$admin_password = "***";
//Enter your email here
$admin_email = "***";
//Your website URL
$home = "http://www.trilogianocturnus.com/main.html";
//Send you an email when someone add your guestbook, YES or NO
$notify = "YES";
//Your Operating System
//For Windows/NT user : WIN
//For Linux/Unix user : UNIX
$os = "WIN";
//Maximum entry per page when you view your guestbook
$max_entry_per_page = 10;
//Name of file used to store your entry, change it if necessary
$data_file = "ardgb18.dat";
//Maximum entry stored in data file
$max_record_in_data_file = 1800;
//Maximum entries allowed per session, to prevent multiple entries made by one visitor
$max_entry_per_session = 10;
//Enable Image verification code, set the value to NO if your web server doesn't support GD lib
$imgcode = "YES";
//Color & font setting
$background = "#000";
$table_top = "#000";
$table_content_1a = "#090909";
$table_content_1b = "#000000";
$table_content_2a = "#090909";
$table_content_2b = "#000000";
$table_bottom = "#000";
$table_border = "#1f1f1f";
$title_color = "#9f0000";
$link = "#9f0000";
$visited_link = "#9f0000";
$active_link = "#9f0000";
$font_face = "verdana";
$message_font_face = "arial";
$message_font_size = "2";
//-- Don't change bellow this line unless you know what you're doing
$do = isset($_REQUEST['do']) ? trim($_REQUEST['do']) : "";
$id = isset($_GET['id']) ? trim($_GET['id']) : "";
$page = isset($_GET['page']) ? $_GET['page'] : 1;
$self = $_SERVER['PHP_SELF'];
if (!file_exists($data_file)) {
echo "<b>Error !!</b> Can't find data file : $data_file.<br>";
exit;
} else {
if ($max_record_in_data_file != "0") {
$f = file($data_file);
rsort($f);
$j = count($f);
if ($j > $max_record_in_data_file) {
$rf = fopen($data_file,"w");
if (strtoupper($os) == "UNIX") {
if (flock($rf,LOCK_EX)) {
for ($i=0; $i<$max_record_in_data_file; $i++) {
fwrite($rf,$f[$i]);
}
flock($rf,LOCK_UN);
}
} else {
for ($i=0; $i<$max_record_in_data_file; $i++) {
fwrite($rf,$f[$i]);
}
}
fclose($rf);
}
}
}
session_start();
$newline = (strtoupper($os) == "WIN") ? "\r\n" : "\n";
switch ($do) {
case "":
$record = file($data_file);
rsort($record);
$jmlrec = count($record);
?>
I have of course, removed the password and email for security, now here isthe funny part.
This error started happening the moment i changed that setting up up there, but if i tried to revert it back to 1800 (i changed it to 11800 to test it out), it still gives me that error.
Any idea of what this is?
The guestbook url is: promosi-web.com/script/guestbook/
The most common cause of this error is something being added to the file before the <?
Most likely a space or UTF byte order mark.
Put your session_start() after <? and you should be fine
Note:
To use cookie-based sessions, session_start() must be called before outputing anything to the browser.
http://php.net/manual/en/function.session-start.php
The message says that the “output started at …\guestbook.php:1”. So there must be something in that file on that line that initiated the output.
Make sure that there are no whitespace or other invisible characters (like a BOM) before the opening <? tag.
Check if you have a space or a byte order mark, you can also do an
ob_start(); at the beginning of the page and ob_end_flush(); at the end to solve this issue.
but IMO check for the space or the B.O.M

Categories