php infinite loop and comet? - php

Something seems wrong with my php script, but I have no idea what it is. The only possible thing that seems to be wrong is something to do with the cache, but I am not sure. Here's my script, I'll tell you what's happened below the code:
<?php
set_time_limit(0);
header('Content-Type:text/event-stream');
$prevmod=$lastmod=filemtime('chattext.txt');
function waitformod(){
global $lastmod;
global $prevmod;
while($prevmod==$lastmod){
usleep(100000);
clearstatcache();
$lastmod=filemtime('chattext.txt');
}
echo 'data:'.file_get_contents('chattext.txt').PHP_EOL.PHP_EOL;
flush();
$prevmod=$lastmod;
}
while(true){
waitformod();
}
?>
This is supposed to be used with the JavaScript EventSource and send the contents of chattext.txt whenever it is modified. The file does not output anything, however. I think it is because of the infinite loop. Is there any way to fix this?

Does something like this work better?
<?php
set_time_limit(0);
header('Content-Type:text/event-stream');
$prevmod = $lastmod = filemtime('chattext.txt');
function waitformod(){
global $lastmod;
global $prevmod;
while($prevmod == $lastmod) {
usleep(100000);
clearstatcache();
$lastmod = filemtime('chattext.txt');
}
echo 'data:'.file_get_contents('chattext.txt').PHP_EOL.PHP_EOL;
flush();
$prevmod = $lastmod;
}
while(1) {
waitformod();
}
Your current code looks like it reads the file, outputs it, waits for it to change, and then terminates.

Related

Output buffering not working as expected?

I have a long-running script and want to use output buffering to send output to the browser periodically.
I'm confused, because I've read a number of questions on here that said to use this:
while (...) {
ob_start();
// echo statements
ob_end_flush();
}
But that didn't work for me. I also tried this:
while (...) {
ob_start();
// echo statements
ob_flush();
flush();
ob_end_flush();
}
But that didn't work either. The only thing that seems to work is this:
while (...) {
ob_end_clean();
ob_start();
// echo statements
ob_flush();
flush();
}
Why do I have to call ob_end_clean() first in order for output buffering to work?
Probably it depends on the rest of your code.
For me the following code works without a problem:
<?php
header( 'Content-type: text/html; charset=utf-8' );
$x = 1;
while ($x < 10) {
echo $x."<br />";
ob_flush();
flush();
sleep(1);
++$x;
}
You can use ob_implicit_flush() but it makes you don't need to run flash() each time you run ob_flush() so above code can be changed to:
<?php
header( 'Content-type: text/html; charset=utf-8' );
$x = 1;
ob_implicit_flush(true);
while ($x < 10) {
echo $x."<br />";
ob_flush();
sleep(1);
++$x;
}
You should also look at your header(). If in any of above codes I remove/comment line with header all the content will be displayed after scripts ends execution. Output buffering won't work as expected
You do it the wrong way. This will do it:
while (...) {
// echo statements
flush();
}
Make sure, your Webserver is configured to delegate the Output without own cache. Output Buffer ob_start is only needed, if you want to get the output later as string.
Also take a look at ob_implicit_flush, which will automaticly perform a flush on output.

session_start() error: why it doesn´t recognize a new session?

I´m testing a php exercise, and I can´t get it working properly. It´s a counter that stores the visits inside a txt file as a simple integer. Every time I reload the page the number gets a +1.
Now, I want it to reload only when there´s a new visit, so I´m trying sesion_start() for the first time.
In class, this example worked just fine, but when I try to reproduce it at home, the number won´t change, even if I close the browser and open it again.
This is my code (it´s inside the php tags, naturally):
session_start();
if (!$_SESSION[contador]) {
define('ARCHIVO', 'visitas.txt');
if (file_exists(ARCHIVO)) {
$fp=fopen(ARCHIVO, 'r');
$cant=fread($fp,filesize(ARCHIVO));
fclose($fp);
} else {
$cant=0;
}
$cant++;
$fp=fopen(ARCHIVO, 'w');
fwrite($fp, $cant);
fclose($fp);
$_SESSION[contador]=$cant;
}
echo '<h3>Hay '.$_SESSION[contador].' visitas.</h3>';
contador should be in quotes unless it's a defined constant somewhere?? I assume it's a string
$_SESSION["contador"]
Try this out. It's different, but it'll do something at least. Would've posted as a comment, but I wanted code formatting.
session_start();
if(empty($_SESSION['contador'])){
$_SESSION['contador']=1;
}else{
$_SESSION['contador']++;
}
echo '<h3>Hay '.$_SESSION['contador'].' visitas.</h3>';
First of all, #Lenny is correct. $_SESSION['contador'] is what is called a session variable or a variable assigned to the $_SESSION array. So it MUST BE in quotes. That is not optional. And you cannot define a constant and use that value inside the brackets.
if you had a constant, you could set the session variable to that. But, since your value is variable, as you are adding incrementally, it is by definition not constant.
Furthermore, refreshing your Web browser will keep your session active. So if you truly want to test this, try session_destroy(); at some point.
Here is how this code will work (the storage of the session variable anyway):
<?php
session_start();
if(!isset($_SESSION['contador'])) {
define('ARCHIVO', 'visitas.txt');
if(file_exists(ARCHIVO)) {
$fp = fopen(ARCHIVO, 'r');
$cant = fread($fp,filesize(ARCHIVO));
fclose($fp);
} else {
$cant=0;
}
$cant++;
$fp = fopen(ARCHIVO, 'w');
fwrite($fp, $cant);
fclose($fp);
$_SESSION['contador'] = $cant;
}
echo '<h3>Hay ' . $_SESSION['contador'] . ' visitas.</h3>';
?>
Note: your logic is bad. Your are telling your script that $cant is either equal to the value of the txt file OR it is equal to 0. Then your are incrementing that value by one. You will perform that task on each load. You need to modify this code and finish your conditional statement.
<?php
session_start();
if(!isset($_SESSION['contador'])) {
define('ARCHIVO', 'visitas.txt');
if(file_exists(ARCHIVO)) {
$fp = fopen(ARCHIVO, 'r');
$cant = fread($fp,filesize(ARCHIVO));
fclose($fp);
} else {
$cant=0;
}
$cant++;
$fp = fopen(ARCHIVO, 'w');
fwrite($fp, $cant);
fclose($fp);
$_SESSION['contador'] = $cant;
} else {
$_SESSION['contador']++;
}
echo '<h3>Hay ' . $_SESSION['contador'] . ' visitas.</h3>';
?>
I hope this helps.

How to stop ignore_user_abort once started?

Whats the best solution to stop a ignore_user_abort actively running on the server in a loop? (PHP)
Basically trying to stop a infinitely looping PHP script that won't stop because ignore_user_abort was set and the script executed ..
Simple exaggerated example :
<?
ignore_user_abort(true);
set_time_limit(0);
$test = 1;
while ($test < 1000000000000000 )
{
sleep(1);
$test = $test+1;
}
?>
It seems connection_aborted is what you're looking for?
<?php
ignore_user_abort(TRUE);
set_time_limit(0);
while (TRUE) {
if(connection_aborted()) {
break;
}
sleep(5);
}
// do some stuff now that we know the connection is gone
?>
Alternatively you could check connection_status against the predefined CONNECTION_ABORTED constant:
if(connection_status() == CONNECTION_ABORTED)
{
break;
}
You can get a good rundown in the manual docs on Connection handling
//this will stop the script after running for 30 sec
set_time_limit(30);

Codeigniter 2.x - Echo output as script is working

I was trying to get codeigniter to output text as the script was working but couldn't get it to work. I have search on here and google and seen using ob_end_flush(); and flush(); and also along with adding more bytes so the browser can output. But none of that is working in CI 2.x. If anyone has had luck with this, thanks in advance
I have tried
function test()
{
ob_end_flush();
echo "test1";
ob_start();
sleep(3);
ob_end_flush();
echo "test1";
ob_start();
sleep(3);
ob_end_flush();
echo "test1";
ob_start();
}
With no luck. The script waits 6 seconds then spits everything out at once. I would like it to echo the output to the screen then wait 3 seconds then output the next echo then wait another 3 seconds etc.
I tried this today and didn't worked either. Then I looked at the core's output class and there was a private _display() function. I figured that the output is collected before it's displayed into some variable then at last this function is called. So before my code in the controller method, I added this line:
$this->output->_display("");
and then ran the code. It worked. So your modified function would be like this :
function test()
{
$this->output->_display("");
ob_end_flush();
echo "test1";
ob_start();
sleep(3);
ob_end_flush();
echo "test1";
ob_start();
sleep(3);
ob_end_flush();
echo "test1";
ob_start();
}
The issue you're having with Code Igniter specifically is that there is already an output buffer in effect. Preceding your test with the following snippet will get you out of php-level buffering at least:
// try to bust out of output buffering
while(ob_get_level()) {
ob_end_flush();
}
ob_end_flush();
As noted by #Wesley, this can still be undermined by your server's configuration, but in my current setup I can stream output back after busting out of all output buffers.
check your server api with
echo phpinfo();
if you found your server api
Server API : CGI/FastCGI
in CentOS Add below line in "/etc/httpd/conf.d/fcgid.conf"
OutputBufferSize 0
Restart your Apache server and try below code
ob_start();
for($i = 0; $i < 10; $i ++) {
echo $i;
echo '<br />';
flush();
ob_flush();
sleep(1);
}

How to check if an include() returned anything?

Is there any way to check if an included document via include('to_include.php') has returned anything?
This is how it looks:
//to_include.php
echo function_that_generates_some_html_sometimes_but_not_all_the_times();
//main_document.php
include('to_include.php');
if($the_return_of_the_include != '') {
echo $do_a_little_dance_make_a_little_love_get_down_tonight;
}
So after I've included to_include.php in my main document I would like to check if anything was generated by the included document.
I know the obvious solution would be to just use function_that_generates_some_html_sometimes_but_not_all_the_times() in the main_document.php, but that's not possible in my current setup.
make function_that_generates_some_html_sometimes_but_not_all_the_times() return something when it outputs something and set a variable:
//to_include.php
$ok=function_that_generates_some_html_sometimes_but_not_all_the_times();
//main_document.php
$ok='';
include('to_include.php');
if($ok != '') {
echo $do_a_little_dance_make_a_little_love_get_down_tonight;
}
If you are talking about generated output you can use:
ob_start();
include "MY_FILEEEZZZ.php";
function_that_generates_html_in_include();
$string = ob_get_contents();
ob_clean();
if(!empty($string)) { // Or any other check
echo $some_crap_that_makes_my_life_difficult;
}
Might have to tweak the ob_ calls... I think that's right from memory, but memory is that of a goldfish.
You could also just set the contents of variable like $GLOBALS['done'] = true; in the include file when it generates something and check for that in your main code.
Given the wording of the question, it sounds as if you want this:
//to_include.php
return function_that_generates_some_html_sometimes_but_not_all_the_times();
//main_document.php
$the_return_of_the_include = include 'to_include.php';
if (empty($the_return_of_the_include)) {
echo $do_a_little_dance_make_a_little_love_get_down_tonight;
} else {
echo $the_return_of_the_include;
}
Which should work in your situation. That way you don't have to worry about output buffering, variable creep, etc.
I'm not sure if I'm missing the point of the question but ....
function_exists();
Will return true if the function is defined.
include()
returns true if the file is inclued.
so wrap either or both in an if() and you're good to go, unless I got wrong end of the stick
if(include('file.php') && function_exists(my_function))
{
// wee
}
try
// to_include.php
$returnvalue = function_that_generates_some_html_sometimes_but_not_all_the_times();
echo $returnvalue;
//main_document.php
include('to_include.php');
if ( $returnvalue != '' ){
echo $do_a_little_dance_make_a_little_love_get_down_tonight;
}

Categories