I just noticed something strange. I thought that, as PHP’s manual says, session_start() must be called before any output is sent to the browser:
To use cookie-based sessions, session_start() must be called before outputing anything to the browser.
So, just for curiosity, I’ve created two scripts. One is write.php:
<?php
echo 'foo';
session_start();
$_SESSION['bar'] = 'baz';
?>
And the other one is read.php:
<?php
echo 'foo';
session_start();
var_dump($_SESSION['bar']);
?>
And surprisingly, the session is written and read even after echoing foo.
However, if I add a call to flush() after the echos, Apache’s error log reports:
[Tue Jan 03 11:57:21 2012] [error] [client 127.0.0.1] PHP Warning: session_start(): Cannot send session cache limiter – headers already sent in /var/www/sessions/write.php on line 5
[Tue Jan 03 11:57:21 2012] [error] [client 127.0.0.1] PHP Stack trace:
[Tue Jan 03 11:57:21 2012] [error] [client 127.0.0.1] PHP 1. {main}() /var/www/sessions/write.php:0
[Tue Jan 03 11:57:21 2012] [error] [client 127.0.0.1] PHP 2. session_start() /var/www/sessions/write.php:5
So, my questions is: why is the session written correctly after echoing something? Isn’t it immediately sent to the browser? And, if so, does it mean I can start the session anywhere, as long as I don’t call flush() before?
That’s true. Server-side side cookie setting (unlike JavaScript cookie setting) works by sending an HTTP header. HTTP headers go before the actual document: once you start sending the document, there’s no place for further headers.
In your case, what happens is that this line:
… does not actually send output to the browser. Instead, it adds some output to a queue that will be sent later. The PHP interpreter is configured to hold this output until certain event happens (possibly, the scripts ends or the queue reaches certain size).
The output_buffering directive is the likely suspect.