Is output buffering not working? - php

(I set output_buffering and implicit_flush to Off.)
I know PHP has its own output buffering. (Not output buffering that starts with ob_start())
<?php
echo 'hello';
header('HTTP/1.1 200 OK');
echo 'hello';
?>
So I expected that the above source code would work fine because of the output buffering unless I call flsuh().
However, a warning occurs. (Warning: Cannot modify header information - headers already sent by)
I do not know why. I want you to let me know if I have misunderstood.

You cannot output anything before setting headers.
Functions that send or modify HTTP headers must be invoked before any output is made, regardless of php.ini settings.
This is why sometimes the unintentional space before or after <?php, ?> will cause this error to be thrown.
In any request, headers are sent first and then output. You are effectively outputting, then sending/modifying headers, and then outputting again.
At the first invocation of any output, PHP will flush header buffers meaning they are already set, so trying to change them after is impossible; and that is why the error occurs.

Related

Call header() after output is sent

According to the PHP documentation:
header() must be called before any actual output is sent, either by normal HTML tags, blank lines in a file, or from PHP. It is a very common error to read code with include, or require, functions, or another file access function, and have spaces or empty lines that are output before header() is called. The same problem exists when using a single PHP/HTML file.
but when I tried the example that the documentation reports (with a little change):
<html>
<?php
/* This will give an error. Note the output
* above, which is before the header() call */
header('X-Header: http://www.example.com/');
exit;
?>
all worked just fine, no error poped up and I smoothly got my <html> tag in the output and my X-Header in the headers.
I'm using PHP 7.1.9, so is still correct what the documentation says?
The documentation is still correct.
For performance purposes, the interpreter puts the output in a buffer. When the buffer is filled for the first time, the interpreter sends the headers then it sends the content of the buffer (and empties the buffer). After this point any call of the function header() fails. The headers cannot be modified any more and other headers cannot be added because the headers have already been sent.
This lets the script produce a small amount of output before sending the headers.
Read more about output buffering configuration settings.
The option output_buffering allows turning the feature off or on and even setting the size of the buffer.
The option implicit_flush tells the interpreter to flush the buffer after every output block. This forces your script to send the headers correctly, before any output.
edit your php.ini and enable Output Buffering ..

Can send header even though I have output

Should'nt the following give an error message? It sends me to domain.com/asdad/ instead of giving me an error message.
<?php
echo 'asdadasdasd';
if ($_SERVER['REQUEST_URI'] == '/newtest.php') {
header("Location: /asdad/");
exit;
}
?>
I view this directly, no other files or code before or after this. Should'nt header give me an error and NOT send me to the new page as I have output before the header?
Check your phpinfo(), you probably have output_buffering switched on.
PHP output, like most IO, is often put into a temporary buffer until a critical amount is reached (or a user calls flush), at which point the contents are flushed to the browser. If you manage to send a header before the output buffer is flushed, you can get away with it.
However, this is not something you rely on, as the buffer size (or, indeed, buffering at all) can vary between installations.

PHP output_buffering on/off issue

I have created a PHP application with output_buffering = On.
Now, if i do output_buffering = Off then i have get following error
"Cannot modify header information - headers already sent by ".
How can i remove this error?
What can be the drawback if i upload application on live site with output_buffering = Off?
From PHP Tag Wiki:
Q. "Headers have already been sent..."
A. You're outputting content and triggering PHP's default content-type:text/html header before making your own call to header(). There are a few ways this can happen, check for a stray echo or print, whitespace before and after the tags or maybe a Unicode BOM. Consider using output buffering. With many scripts, there is no need to include the ending ?> and the problem is easily fixed by removing the ending ?> tag from your files.
There is also a myriad of duplicates for this.
Send out your headers before any output goes to the browser.
header('Foo: bar');
echo "foo";
If you turn output buffering off, you are not allowed to send any additional headers (this includes cookies e.g.) after you've send any piece of data to the client (namely using echo or some other output function).
You can use headers_sent() to check where you started to output data to the client.
Ensure all header('') tags go right at the top of the script with no white space!
EG:
<?php
header('type of header');
?>
If you really have to do it further down the page you can call ob_start() at the top of the script. Call ob_end_flush() at the end of the script too.

Able to Echo before header()

Came across something strange while migrating to my new server.
I have a script that will redirect users to another web page based on certain conditions. What I was doing, however, is echoing out 'Redirecting...', then using the header() function to actually redirect. Here is how the code looked:
if( $condition ) {
echo 'Redirecting...';
header( 'Location: ' . $url );
}
Now I only noticed that this is incorrect after switching over to our new server, tested it out, and saw that it would NOT redirect just output Redirecting... and once I searched about it, learned you cannot have any kind of output (unless using ob_start etc) before using the header() function.
Question is, why is this code, that should NOT work in ANY PHP installation, work on my old server? It will redirect with the echo before header() no problem.
Thanks!
You may have had output buffering on on the old server: output buffering will not output anything until the script finishes running. That allows it to get the header out before the actual output (as it knows the headers should be sent first).
If that makes sense.
Maybe your old installation had output_buffering defined to true in the php.ini. This delayed the output allowing you to set the headers even after echoing.
You must have had buffering turned on, even though you did not actively do so yourself. output_buffering = On in php.ini?
It worked on your old server as you had output buffering on by default, set by the php.ini.
The old server probably had output buffering enabled by default. This meant that it wouldn't echo right away, but rather wait until the whole script has finished, and then echo. This also means that the header would be sent before the echo (since it was buffered), and therefore would not result in a warning.
On the new server, you most likely do not have output buffering enabled by default, and this would mean that it would echo straight away, without buffering it, and therefore it would be sent before the headers and result in a warning.
I would encourage you to use headers_sent() to check if the headers has been sent before using headers() after echo, like this:
<?php
echo "Foobar\n";
if(!headers_sent())
header('Location: /helloworld.php');
?>
Related links:
Output Control
Runtime configuration for Output Control - how to enable output control in your php.ini file
ob_start() function for manually enabling output buffering anywhere in your script.
header_sent()

why ob_start() must come ahead of session_start() to work in PHP?

I don't think it's reasonable.
Why is it actually such a rule?
In the "normal case", I don't think ob_start has to be called before session_start -- nor the other way arround.
Quoting the manual page of session_start, though :
session_start() will register internal
output handler for URL rewriting when
trans-sid is enabled. If a user uses
ob_gzhandler or like with ob_start(),
the order of output handler is
important for proper output. For
example, user must register
ob_gzhandler before session start.
But this is some kind of a special case : the thing is, here, that the order of output handlers is important : if you want one handler to modify things the other did, they have to be executed in the "right" order.
Generally, if you don't use that kind of handlers (Apache and mod_deflate do a great job when it comes to compressing output, for instance), the only thing that matters is that headers must not be sent before you call session_start (because, depending on your configuration, session_start sends cookies, which are passed as HTTP headers).
And headers are sent as soon as any piece of data has to be sent -- ie, as soon as there is any output, even one whitespace outside of <?php ?> tags :
Note: If you are using cookie-based
sessions, you must call
session_start() before anything is
outputted to the browser.
ob_start indicates that PHP has to buffer data :
This function will turn output
buffering on. While output buffering
is active no output is sent from the
script (other than headers), instead
the output is stored in an internal
buffer.
This way, output is not sent before you actually say, yourself, "send the data". This means headers are not send immediatly -- which means session_start can be called later, even if there should have been output, if ob_start had not been used.
Hope this makes things a bit more clear...
If by default your output_buffering is Off and you have been unfortunate enough to send a single byte of data back to the client then your HTTP headers have already been sent. Which effectively prevents session_start() from passing the cookie header back to the client. By calling ob_start() you enable buffering and therefore delay sending http headers.
session_start might want to modify the HTTP header if certain configuration options are set. One for example is session.use_cookies that requires to set/modify the Set-Cookie header field.
Modifying the HTTP header requires that there isn’t any output that’s already sent to the client as the HTTP header is sent right before the first output is sent.
So you either ensure that there is absolutely no output before the call of session_start. Or you use the output buffering control to buffer the output so that the HTTP header can be modified even if there already is output.
session_start() will register internal output handler for URL rewriting when trans-sid is enabled. If a user uses ob_gzhandler or like with ob_start(), the order of output handler is important for proper output.
For example, the user must register ob_gzhandler before session start.
But this is some kind of a special case. The thing is, here, that the order of output handlers is important. If you want one handler to modify things the other did, they have to be executed in the "right" order.
Generally, if you don't use that kind of handlers (Apache and mod_deflate do a great job when it comes to compressing output, for instance), the only thing that matters is that headers must not be sent before you call session_start (because, depending on your configuration, session_start sends cookies, which are passed as HTTP headers).
And headers are sent as soon as any piece of data has to be sent -- ie, as soon as there is any output, even one whitespace outside of <?php ?> tags :
Note: If you are using cookie-based sessions, you must call session_start() before anything is outputted to the browser.
ob_start indicates that PHP has to buffer data :
This function will turn output buffering on. While output buffering is active no output is sent from the script (other than headers), instead the output is stored in an internal buffer.
This way, output is not sent before you actually say, yourself, "send the data". This means headers are not send immediatly -- which means session_start can be called later, even if there should have been output, if ob_start had not been used.
session_start(); should be called before any headers are sent out. ob_start() will suppress the output for a while and you can break this rule. Usually ob_start() on the top is a quick fix in case you are debugging something unknown; everything below works as expected (not just as written ;-)). I prefer to use ob_start() later to session_start().
In PHP, ob_start() is used to start output buffering. Output buffering captures all output sent to the browser and stores it in a buffer, allowing you to manipulate it before sending it to the browser.
When using sessions in PHP, it is important to call ob_start() before starting the session, as sessions rely on cookies, which are sent to the browser as part of the HTTP headers. If any output has already been sent to the browser before the session is started, the headers will have already been sent and it will not be possible to set the session cookies.
By calling ob_start() before starting the session, any output that is generated before the session is started will be captured by the buffer and will not be sent to the browser. This allows the session cookies to be set correctly, even if some output has already been generated.
In summary, ob_start() is necessary for session in PHP because it ensures that headers can be sent correctly even if there is output generated before the session is started.

Categories