The docs I read don't seem clear on this issue.
When calling exit() with no arguments, does the server still send something back to the client?
If so, is there an alternative or way to keep anything from being sent to the client on exit?
exit is basically the same as reaching the end of the file. Anything that has already been sent will be received by the browsers, and any output buffers will be processed and also sent.
You can force an empty response by include ob_start() as your first line of code, and using this function:
function exitEmpty() {
while(ob_get_level()) ob_end_clean();
exit;
}
However the headers will still be sent. This just empties the response body.
exit() will still send headers, if they haven't already been sent, but otherwise it will send nothing else.
Related
The headers_sent() function from php does not work on my target server. It does not evaluate to True even when things are echoed. This can be fixed by changing the output_buffering value in php.ini but unfortunately I do not have access. A workaround as mentioned in this stackoverflow question is to use the flush() function.
However when using flush() the headers_sent() function always evaluates to True. This is because flush() will send headers + content(if any) as lafor pointed out .
<?php
flush();
if(headers_sent())
echo 'headers were sent';
//will output 'headers were sent'
I wanted to use the headers_sent() function to check if anything has been written/outputted yet.
The headers itself are not of importance to me.
Can anyone help me with a way of checking if there has been some output earlier?
(extra context: I want to check if any functions did echo() some warning messages earlier in execution time, of course these functions could/should also do some more sophisticated error reporting, but that is a different story)
What is your purpose for doing this? A little more explanation might help us put it into context.
If output buffering is needed, you can skip the php.ini function and just use ob_start(); and a function like ob_get_clean(); to return the contents without outputting.
http://us1.php.net/flush describes a number of cases where buffering may cause output not to be sent when expected. See also http://www.tuxradar.com/practicalphp/13/9/0#null. The flush() function is supposed to send "everything" to the browser, which would include HTTP headers. However, it's not clear from what I've read whether the headers are sent even if there is no other output. From your reported experience, I would surmise that at least for your server (and maybe browser), headers are flushed regardless of whether there is other output.
When output buffering is on, headers don't get sent until the output is flushed, so headers_sent() returning false before that is correct.
flush() flushes all buffered content (if any) and headers, so headers_sent() returning true after that is also correct. I don't see how the function is "not working" or "useless".
If your purpose is to check whether any headers were set to be sent (using header() function which, with no output buffering, would also send the header right away), you might wanna look into headers_list() or register a custom callback with header_register_callback().
In PHP, is there a (ready-made) way to check if a part of the output has already been sent to the client?
I know that with headers_sent() you can check if the headers have already been sent, but I also want to check if any output has been sent (so that e.g. the HTTP header Content-Length > 0).
(Notice that ob_start() starts output buffering from the moment when it is called. But third-party systems implementing my code might already have sent output, thus output buffering is unusable as far as I know.)
You could wrap your own ob_start around everything else and flush it when you decide to. It works even if other ob_start's and flushes are inside. Take this example :
ob_start();
[...]
//some 3rd party app which is included on the way
[...]
ob_start();
[...]
ob_flush(); //at this moment the buffer isn't flushed to the client
//but to the parent ob_start, which is yours, so no output
//is sent yet
[...]
//ok, we're done, we can output now
ob_flush();
PHP in most cases sends headers to Apache only with some content or on the end of script execution. So, if headers are sent, some content is sent too. Furthemore, as I understand, Content-Length is calculated anyway after the script execution.
I'm trying to design a page which does some database actions, then redirects to user back to the page they came from. The problem is that I use a require() function to get the connection to the database, so the headers are already sent. A meta tag is out of the question since I want it to look like all the processes are done from the page they came from. Any tips? Is there a way I can use the require() and the header() or do I have to drop one? Is there an alternative to header()?
If you can't send the header() before some content gets sent, use output buffering by placing an ob_start(); at the beginning of your script before anything is sent. That way, any content will be stored in a buffer and won't be sent until the end of the script or when you manually send the buffer's contents.
On another note, simply requireing another file would not generate any headers/content unless that included script sends them. The most common "hidden" cause of this is unnoticed whitespace before or after the <?php ?> tags.
As Artefacto noted, connecting to the database should not require any output. Fix whatever you're including (e.g. database_connect.php) not to output. See this search on the "headers already sent" issue, which may help you find "hidden" output.
ob_start(); // start output buffering
echo "<html......"; // You can even output some content, it will still work.
.
.
.
.
.
header("Location: mypage.php");
ob_flush(); //flush the buffer
In this case, all output is buffered. This means, the headers are processed first, then the output comes to play...
You cannot send any headers after some content has already been sent. Move the header() call to be before the require() call.
You cannot send headers after any data has been sent to the client.
However, using require does not meen that you output something. If i understand your right, you can include your database files, run your queries and then redirect the user. This is perfectly valid.
If you need to send some output (why if you need to do a redirect?) another option is to use output buffering. By using output buffering, you're not sending the data to the browser when you echo it, but you store it in a buffer. The data will be sent when you call ob_end_flush or you reach the end of the script. After ob_end_flush, you won't be able to send any new headers. You start output buffering with ob_start.
It is possible to use header() with require() when I use output buffering. That means that the whole script is buffered and first send when the script has come to an end.
I have done it by doing this
ob_start("ob_gzhandler"); //begin buffering the output
require_once('/classes/mysql.php');
// Some code where I access the database.
header('/somepage.php');
exit;
ob_flush(); //output the data in the buffer
how can I set cookies in the middle of a document, without incurring a 'headers already sent' error? What I'm trying to do is make a log out script (the log in cookie setting works...so odd. Is it because it's enclosed in an if statement?) however I've already echoed the page title and some other stuff at the top of the page, before I've made this logout happen.
Thanks!
The easiest way is to use output buffering to stop PHP from sending data to the client until you're ready
<?php
ob_start();
// your code
ob_end_flush();
?>
Output buffering stores all outputted data until the buffer is flushed, and then sends it all at once, so any echos after the start will remain buffered until the end_flush and then sent
Try to decompose your application in two parts :
First, you unset the cookie, then you redirect user on the result page. It's a common way to work.
Also try to use a framework in your development, it will improve your skills and the maintenability of your code.
Cookies are sent in the headers, which are sent before anything else is sent. Therefore, if you have actually 'echoed' something to the client (browser), your headers have also been sent.
That said, you can buffer your output and send it all once all the code has been run (ob_start() and ob_end_flush())
I'm using set_cookie() on a site. After adding some functionality, I'm getting Warning: Cannot modify header information - headers already sent by... error. The line number it references as to where the headers initiated from is the very line where set_cookie() is! And I checked, it's not being called twice.
How can I track down these premature headers? I looked at the source code and didn't see any stray characters or anything before the error message starts ( I'm using xdebug, so the first thing is a , which I thought was me, but is actually the beginning of the xdebug message ). I've grepped my code for extra echo and so forth -- nothing.
Can PHP tell me when and where the headers are starting? Or are they really starting on the set_cookie line, and if so, how have I gotten myself into this situation, and how do I get out?
edit: I'm not sure I can paste the code -- do you want just the set_cookie() line? I thought the headers were coming out before that. And there's a lot going on before that with different classes being instantiated. And also I don't think I can post all the classes and stuff -- you know, proprietary information ;)
Edit: I've gotten rid of all terminating delimiters ( all ?>s) and made sure that the first characters of every included file is <?. This is frustrating! It was working before I did these recent changes :(((
Also, why doesn't headers_sent() work?
if ( headers_sent($filename, $linenum) ) {
echo "headers sent: $filename:$linenum.";
}
set_cookie(...);
gives
headers sent: :0.
You can use headers_sent():
if (!headers_sent($filename, $linenum)) {
set_cookie(/*...*/);
} else {
echo "Headers already sent in $filename on line $linenum\n";
exit;
}
One approach would be to run your script from the command line with STDERR redirected to null.
This will show you everything that is being sent to STDOUT, i.e. everything that the server would send to a client.
Hopefully, once you see this, it will be clear where your headers are coming from.
Besides using headers_sent to detect if the HTTP header has already been sent, you could use the PHP’s output control to buffer the output. That allows you to change the header even if you’ve already done some output.
Here’s some example using the explicit output buffering by calling ob_start:
ob_start();
echo 'foobar';
header('Content-Type: text/plain;charset=utf-8');
But make sure you call ob_start before any output was done. Otherwise the HTTP header probably has already been sent.
Can you paste the code?
If its saying headers already sent by [line where set_cookie is], then the error is further on in the script.
Are you sure that you don't have any include files being called prior to your set_cookie() initialization? Do you have sessions running, because if you do, you could just set the cookie at that same point in your script as you started the session.
If there is even a single white space before your set_cookie() initialization it will cause the headers to not be sent correctly. Maybe try using a different editor and checking your results.
I found it! It was a flush(); that I had left lying around all by itself in one of the pages. Surprisingly, it doesn't correctly bind $filename and $linenumber to headers_sent().