jhsachs Posted July 27, 2011 Share Posted July 27, 2011 I just got this message when I moved a new, supposedly debugged version of software to my client's staging site: Cannot send session cache limiter - headers already sent... I found the problem without a lot of difficulty: an included file was sending JavaScript code to the browser before a call to session_start(). It's not clear to me why session_start sets a cache limiter, but apparently it does. My question is why this problem did not appear on my development system. The same code was executed there; it presumably tried to do the same thing, and did so after the JavaScript was sent. Yet everything worked perfectly. That's bad behavior; if it's going to fail on the staging site (or the production site!) I want to to fail when I'm deugging. Quote Link to comment https://forums.phpfreaks.com/topic/242988-sending-output-to-browser-before-headers-why-did-it-work/ Share on other sites More sharing options...
Pikachu2000 Posted July 27, 2011 Share Posted July 27, 2011 My guess would be that your development box doesn't have error reporting set at a high enough level, display_errors is Off, or it's set up to use output buffering by default via the output_buffering directive in the php.ini file. Quote Link to comment https://forums.phpfreaks.com/topic/242988-sending-output-to-browser-before-headers-why-did-it-work/#findComment-1248036 Share on other sites More sharing options...
jhsachs Posted July 28, 2011 Author Share Posted July 28, 2011 My guess would be that your development box doesn't have error reporting set at a high enough level.. Not that. Each script includes a common file that sets it to E_STRICT+E_NOTICE on both systems. ...display_errors is Off... Not that either. I get error notices when I expect them... except in this case. I checked phpinfo and it confirms that the setting is on. ...or it's set up to use output buffering by default via the output_buffering directive in the php.ini file. For a while I thought this was it. php_info reported that output_buffering is "no value" on the staging system, and 4096 on my development system. But I set it to "off" on the development system through .htacess, and init_get() confirms that it is "off," but my script still doesn't get the error. Maybe "no value" has a different effect than "off." I haven't previously encountered a "no value" value, and I don't know how to set it, so I can't test that theory! I think you've got me on the right trail, but the quarry is not yet in sight. Quote Link to comment https://forums.phpfreaks.com/topic/242988-sending-output-to-browser-before-headers-why-did-it-work/#findComment-1248272 Share on other sites More sharing options...
jcbones Posted July 28, 2011 Share Posted July 28, 2011 ; By default, PHP is set to take action on all errors, notices and warnings EXCEPT ; those related to E_NOTICE and E_STRICT, which together cover best practices and ; recommended coding standards in PHP. For performance reasons, this is the ; recommend error reporting setting. Your production server shouldn't be wasting ; resources complaining about best practices and coding standards. That's what ; development servers and development settings are for. ; Note: The php.ini-development file has this setting as E_ALL | E_STRICT. This ; means it pretty much reports everything which is exactly what you want during ; development and early testing. ; E_NOTICE - run-time notices (these are warnings which often result ; from a bug in your code, but it's possible that it was ; intentional (e.g., using an uninitialized variable and ; relying on the fact it's automatically initialized to an ; empty string) ; E_STRICT - run-time notices, enable to have PHP suggest changes ; to your code which will ensure the best interoperability ; and forward compatibility of your code I would suggest changing your runtime settings (common file) to E_ALL. Quote Link to comment https://forums.phpfreaks.com/topic/242988-sending-output-to-browser-before-headers-why-did-it-work/#findComment-1248291 Share on other sites More sharing options...
jhsachs Posted July 28, 2011 Author Share Posted July 28, 2011 I tried setting E_ALL and E_STRICT|E_ALL. Neither one got me messages. (I also found a dumb error: I was setting the error reporting level after the point where the error occurred. I'm glad I found that, but fixing it didn't help.) I've got a nagging feeling that there's some missing piece to this puzzle, but I don't know what it is. I'm attaching phpInfo dumps from my development system and the staging system, in case they suggest something to you. [attachment deleted by admin] Quote Link to comment https://forums.phpfreaks.com/topic/242988-sending-output-to-browser-before-headers-why-did-it-work/#findComment-1248297 Share on other sites More sharing options...
PFMaBiSmAd Posted July 28, 2011 Share Posted July 28, 2011 If your code works on your development system, then output_buffering must be on at some point. I.E. even if the error_reporting/display_errors are set to hide errors, the output would still be occurring and stop the session_start from working. Your error_reporting on both systems is definitely not E_ALL (or even better a -1). Quote Link to comment https://forums.phpfreaks.com/topic/242988-sending-output-to-browser-before-headers-why-did-it-work/#findComment-1248299 Share on other sites More sharing options...
jhsachs Posted July 28, 2011 Author Share Posted July 28, 2011 I wrote this script to isolate the problem: <?php error_reporting(-1); $buffering = "output_buffering=" . ini_get('output_buffering') . "<br/>"; $buffering .= "error_reporting=" . ini_get('error_reporting') . "<br/>"; $buffering .= "display_errors=" . ini_get('display_errors') . "<br/>"; $buffering .= "<br/>1:"; $buffering .= isset($_SESSION) ? var_export($_SESSION,true) : "_SESSION not set<br/>"; session_start(); echo "Session started</br>\n"; echo $buffering; echo "<br/>2:"; var_dump($_SESSION); ?> Here's its output: Session started output_buffering=off error_reporting=-1 display_errors=1 1:_SESSION not set 2: array empty I examined the page source to see if there were extra spaces before the intended output. There were not. Then I added the following line before the call to session_start: echo "Session not yet started<br/>"; Here's the output: Session not yet started Session started output_buffering=off error_reporting=-1 display_errors=1 1:_SESSION not set 2: array empty Still no errors. I'm not saying you're wrong, but I don't understand how to reconcile these results with what you're saying. One other thing puzzles me about this: I thought that session_start set $_SESSION['LAST_ACTIVITY'], but it's not there. Maybe that's it doesn't get set until the cookie is written, and this is normal. Quote Link to comment https://forums.phpfreaks.com/topic/242988-sending-output-to-browser-before-headers-why-did-it-work/#findComment-1248612 Share on other sites More sharing options...
PFMaBiSmAd Posted July 28, 2011 Share Posted July 28, 2011 If your session_start() statement did not produce an error message (like the error in the first post in this thread) when you echoed something before it, then either the error_reporting/display_errors or the output_buffering settings are not actually what are being shown (php has had a history of displaying settings that it is not actually using.) In the same code, try to cause php errors. Add something like the following to see if you get any error messages - echo $i_dont_exist; Quote Link to comment https://forums.phpfreaks.com/topic/242988-sending-output-to-browser-before-headers-why-did-it-work/#findComment-1248619 Share on other sites More sharing options...
jhsachs Posted July 28, 2011 Author Share Posted July 28, 2011 Roger that. I added the line $buffering .= $imaginary; before the line that calls isset(), and I got this (with nice colors and formatting that didn't survive cut and paste): ( ! ) Notice: Undefined variable: imaginary in D:\htdocs\login\sessionbug.php on line 7 Call Stack # Time Memory Function Location 1 0.0038 60784 {main}( ) ..\sessionbug.php:0 Session not yet started Session started output_buffering=off error_reporting=-1 display_errors=1 1:_SESSION not set 2: array empty It really does appear to be displaying errors. Quote Link to comment https://forums.phpfreaks.com/topic/242988-sending-output-to-browser-before-headers-why-did-it-work/#findComment-1248704 Share on other sites More sharing options...
jhsachs Posted July 30, 2011 Author Share Posted July 30, 2011 PFMaBiSmAd: I appreciate your efforts to help me so far, but I wonder what is happening now. Your earlier responses came within hours, but I've waited a couple of days for your response to my last post. If you're out of ideas or time, please let me know so that I can look elsewhere. If not, I'm happy to wait, but I'd like to confirm that I'm waiting for something that's going to happen! Quote Link to comment https://forums.phpfreaks.com/topic/242988-sending-output-to-browser-before-headers-why-did-it-work/#findComment-1249515 Share on other sites More sharing options...
PFMaBiSmAd Posted July 30, 2011 Share Posted July 30, 2011 I didn't see that your reply #8 had been posted (sometimes the SMF software doesn't show all posts when you click the "show unread posts since your last visit" link.) Are you actually using a web server on your localhost development system? It would appear that you are using some IDE or debugger and one or both of them could be causing the unexplained symptoms (in fact most debuggers work by manipulating the actual code that is executing and using output buffering to capture the debugging output.) Quote Link to comment https://forums.phpfreaks.com/topic/242988-sending-output-to-browser-before-headers-why-did-it-work/#findComment-1249520 Share on other sites More sharing options...
jhsachs Posted July 31, 2011 Author Share Posted July 31, 2011 I'm doing most of my work with NetBeans and XDebug. XDebug displays page output by opening a new tab in an independent browser, in my case Firefox 4.0. It was appealing to think that the pages are acting weird because I'm running my scripts in the debugger, but it turned out not to be so. I tried running my current test code on my development system without the debugger, and still got no errors. I uploaded the same code to the staging server and got the same old errors! Quote Link to comment https://forums.phpfreaks.com/topic/242988-sending-output-to-browser-before-headers-why-did-it-work/#findComment-1249988 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.