I'm trying to set up a timeout test on a selection of files. The files run the test via an include, which contains the following:

$inactive = 20;
/* check to see if $_SESSION['timeout'] is set */
if(isset($_SESSION['timeout']) ) 
	{
	$session_life = time() - $_SESSION['timeout'];
	if($session_life > $inactive)
                {
		session_destroy();
		header('Location: logout.html');
		}
	}
$_SESSION['timeout'] = time();

Each of the pages using it begin as follows:

session_start();
include ("data_fr443zzw/timeout.dat.php"); /* Timout test */

6 of the pages work as I'd expect, redirecting on timeout, but one does not. The only difference I can see is that the 6 pages are presentational and have HTML and forms as well as PHP in them. The failing page is pure PHP, dealing with POST and SESSION variables to redirect the browser to the appropriate page.

The failing page effectively continues past the included code and executes that, redirecting based on POST variables, rather than the timeout SESSION variable it encounters first. If I add "die()" after the include on this page, for example, the timeout works, redirecting before executing the die().

So I'm baffled. Any ideas?

Dani AI

Generated

Short answer: the timeout include was sending a redirect but the script kept running and the page’s own POST-handling later performed its own redirect (or otherwise changed the response), so the timeout header never became the final action. As discovered, stopping execution immediately after sending a redirect fixes the symptom — that’s why adding a die()/exit() made things work. ’s observation that the six HTML pages behaved differently is also common: output buffering, BOMs or where/when output is produced can make the visible behaviour vary between files.

Quick diagnostics you can run (fast and non-destructive)

  • Add a headers-sent check to log exactly where output started:
if (headers_sent($file, $line)) {
    error_log("Headers already sent in $file on line $line");
}
  • Search included files for stray whitespace or a UTF‑8 BOM (0xEF 0xBB 0xBF) at the start; many editors can save “UTF‑8 without BOM” to remove it.
  • Turn off display_errors or log errors instead — PHP warnings printed before a redirect will count as output.
  • Omit the closing ?> in pure‑PHP files to avoid accidental trailing whitespace.

Safer patterns / fixes to prevent regressions

  • Make the timeout check return a status (or throw) instead of performing the redirect itself. Let the calling script decide and then stop processing (so later POST logic can’t override it).
  • If the include must redirect, ensure session state is saved (session_write_close()) and immediately stop execution so no further headers or redirects are sent.
  • Consider enabling output buffering (or explicitly calling ob_start() at the very start of your bootstrap) so accidental output won’t break header logic.

These steps will let you pinpoint whether the cause is earlier output (headers_sent) or later code overriding the redirect, and will make the timeout behavior consistent across both presentational and pure‑PHP pages.

Recommended Answers

All 6 Replies

A header redirect has to be before any output. So once something is printed to the screen or HTML is shown, then the redirect will not work.

A header redirect has to be before any output. So once something is printed to the screen or HTML is shown, then the redirect will not work.

Mikulucky, thanks, I know: the six pages that work are the only ones that send anything to screen - the header works fine in them as it is correctly placed.

The one that doesn't is pure PHP, no html (and all pages begin identically anyway, that being the problem).

Mikulucky, thanks, I know: the six pages that work are the only ones that send anything to screen - the header works fine in them as it is correctly placed.

The one that doesn't is pure PHP, no html (and all pages begin identically anyway, that being the problem).

Have you tired, putting an exit(); after the redirect. This is because sometimes I have noticed that the header is sometimes ignored, unless the presence of and exit(); .

So;

$inactive = 20;
/* check to see if $_SESSION['timeout'] is set */
if(isset($_SESSION['timeout']) ) 
	{
	$session_life = time() - $_SESSION['timeout'];
	if($session_life > $inactive)
                {
		session_destroy();
		header('Location: logout.html');
                exit();
		}
	}
$_SESSION['timeout'] = time();

Have you tired, putting an exit(); after the redirect. This is because sometimes I have noticed that the header is sometimes ignored, unless the presence of and exit(); .

So;

$inactive = 20;
/* check to see if $_SESSION['timeout'] is set */
if(isset($_SESSION['timeout']) ) 
	{
	$session_life = time() - $_SESSION['timeout'];
	if($session_life > $inactive)
                {
		session_destroy();
		header('Location: logout.html');
                exit();
		}
	}
$_SESSION['timeout'] = time();

Ah, thanks. No idea why this should be needed but it does seem to create the required functionality across the board. Shall go beta test properly..

Thanks again!

No problem, once done, could you mark as solved and give rep as you feel appropriate?

Thanks

No problem, once done, could you mark as solved and give rep as you feel appropriate?

Thanks

Once I feel it's solved, of course. I'm not happy that it's contrary to programming logic, and therefore suggests issue with PHP, but I'll test it out properly and keep thinking where I may have misunderstood something.

If tests pan out, happy to close and give credit.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.