Can send header even though I have output - php

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.

Related

Why does this header location redirect work after content has already been echoed?

<?
echo "lalala";
header("Location: http://www.google.com/");
If i put this in a plain php file and deliver over a standard apache2 server with mod-php (PHP Version 5.3.2-1ubuntu4.10) the redirect to google works.
<?
echo "lalala";
flush();
header("Location: http://www.google.com/");
this code does obviously not produce a working redirect.
My question is how the first code is beeing processed and why it works. Because I remember times when things like this were not possible. Is mod-php or apache intelligent enough to buffer the whole request and arrange headers before content?
And:
Can I rely on this if I make sure I don't flush the output manually? Because it would make my application much easier...
Output buffering is probably enabled by default. You should enable it manually if you want to rely on this functionality.
http://php.net/manual/en/function.ob-start.php
The header function ADDS an http common header to the HTTP response. So, the redirect is setted and the browser gets the 302 message before showing you the output.
flush orders php to send the http response already prepared at the point it is called. That's why the second code won't set the header (it must be setted before sending ANY output).
And, the PHP should not output a single thing until:
The script is processed (even if an error stops the parsing)
you set it to send the output somewhere in the script with flush()
Finally, check this on output control http://www.php.net/manual/en/intro.outcontrol.php

Set a cookie after output has been send to browser

Is there a way that I can set a cookie after an html output? According to PHP manual setcookie() should be set before the output.
I need it for my voting system wherein a cookie will be set after a successful Mysql query. I made it in one file.
you can use the output buffers so at the top of your script you add ob_start() and this will create a buffer and you can then set the cookie and then end the buffer and flush out to the browser.
ob_start();
/* set cookie */
ob_end_flush();
Is there a way that I can set a cookie after an html output?
Technically no. If you would like to set a cookie you need to ensure that no output has been send to the browser so far.
According to PHP manual setcookie() should be set BEFORE the output.
That's correct, otherwise it won't work. So I would even say must, not only should.
I need it for my voting system wherein a cookie will be set after a successful mysql query.
A successful mysql query on it's own will not create any output. Only a failed mysql query would if error reporting is enabled. So I wonder if you actually ran into a concrete problem or not.
The mysql query itself should not prevent you from using setcookie.
In case you have done already HTML output prior the use of setcookie you need to find the place where your HTML output started. Above that line place the ob_startDocs function which will start output buffering.
With output buffering enabled, your program can still "output" HTML but it will not be send immediately. Then you should be able to call setcookie with no problems:
<?php ob_start(); ?>
<html><body>
<?php
$result = mysql_run_query($query);
echo '<h1>Your Voting Results</h1>';
output_voting_result($result);
set_cookie('vote', $result['id']);
?>
</body></html>
The output buffer will be automatically send to the browser when your script finishes, so there is not much more you need to care about, the rest works automatically.
Cookies can be set in JavaScript on the client side - see this link for examples: http://www.w3schools.com/js/js_cookies.asp
No. Cookies are sent in the header so they must be set before the output body begins.
You can, however, use PHPs built-in buffering so it won't actually generate any output until the script has completely finished executing.
ob_start is the function you want.
You can use output buffering
ob_start();
// send output
// set cookie
ob_end_flush();
The cookie gets set in the http header. If what you want to do is set the cookie on a vote, then you either need to do a header('Location:...') redirect, or you could have a small iframe where you make an ajax call that does the same thing.
Cookies are sent to the browser as part of the response header. This means that they must be set before the server starts writing its response to the request that is being processed (so that the server can specify the correct headers on the response).
I don't know the specifics about how this is handled in PHP, but if I had to guess I would say that the output of a given PHP script is probably buffered by the server (typically Apache) until the script completes, and then the server writes the response after the PHP script has completed execution. If this is the case, then you should be able to set cookies whenever you want. If it isn't, then you won't be able to.
I'd suggest simply testing it to see what happens. Write a PHP script that sets a cookie at the very end of its execution, access it via a browser, and then check to see if the cookie is actually set.
If for some reason you can't buffer the output, you can set a cookie after sending output by displaying an image on the current page that accesses a script that sets a cookie.
echo ('<img src="http://example.com/mysetcookie.php?uid='.$userId.'">');
mysetcookie.php
<?php
setcookie('cookie-name',$_REQUEST['uid']);
//output an image - this is a one-pixel clear image
header('Content-Type: image/gif');
echo base64_decode('R0lGODlhAQABAJAAAP8AAAAAACH5BAUQAAAALAAAAAABAAEAAAICBAEAOw==');
exit;
?>

PHP redirect without header() or meta

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

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()

How to set cookies via PHP in the middle of a document?

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())

Categories