Assume I have a form on index.php and it points to test.php which process the data submitted.
index.php looks like the below:
<form action="test.php"></form>
It should cause an error if test.php looks like the below:
( As you can see, there is already an output Nice being sent before the header () )
echo 'Nice';
header ( "Location: https://example.com" );
But what if I put it inside a function and call the function?
echo 'Nice';
function process () {
header ( "Location: https://example.com" );
}
process ();
Would it works in this case since it's inside a function, and would it cause an error?
As stated here:
https://www.php.net/manual/en/function.header.php
Remember that 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.
So the problem would arise only because you called it after echoing text to the response while you had to do it before.
header ( "Location: https://example.com" );
echo 'Nice';
Calling it inside a function doesn't change that requirement, because the header is part of the response that you already sent echoing text.
Short answer:
header ( "Location: https://example.com" );
To:
echo "<script> window.location.href='https://example.com </script>" ;
The issue is that you are sending an output for the user to see "Nice!" before setting the redirect header. When you send Nice! The server is forced to send the packets with a Header already. You have to learn more about how HTTP protocol works.
The header is like the label on the envelop when you mail it via postal service. The content "Nice" is like the letter inside the envelope. You are trying to send a letter to your friend and then change the label address after it arrives.
Instead for that kind of functionality what you could do is use HTML or Javascript to make the redirect. (HTML way is an obsolete way) so I gave you the Javascript. However this is not good way of writing code but it works and I do it all the time.
Since you seem to like to output things after redirecting user you might want to buffer your output or simply give some time for the redirect to process:
<?php
echo 'Nice';
?> <!--NOTICE I CLOSED PHP TAG -->
setTimeout(function() {
window.location.href = ‘https://example.com/’;
},5000);
Please wait while we redirect you in 5 seconds or simply <a href="https://example.com">click here.<a>
<?php
echo "I like to write PHP code";
?>
It's so refreshing to see a year 2000 style of coding and redirects. :)
Cheers! Very Nice!!!
It might be useful to understand why there is an error if you call header() at the wrong time.
The response from your web server to a browser looks something like this, with a status, then "headers", then a "body":
HTTP/1.1 200 OK
Content-Type: text/html
Nice
When you call header(), you are asking the server to add a line next to the Content-Type, before the "body". (And adding a Location header in particular also changes the status code in the very first line from 200 to 301 to indicate a redirect.) Roughly like this:
HTTP/1.1 301 Redirected
Content-Type: text/html
Location: https://example.com
Nice
If the server has already sent the first version, because you told it to output "Nice", there's no way for it to "take it back" and send the second version. That's just as true in your second code as in your first: you're telling the server to output "Nice", and then telling it to go back and edit the headers, but it's too late.
Related
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Headers already sent by PHP
I have a PHP file which I'm using to check username and password. This part is working, but after successful login I would like to use header() to redirect to user panel page. This is the logged error that I'm getting:
[10-Dec-2012 12:25:26] PHP Warning: Cannot modify header information - headers already sent by (output started at /home2/jzperson/public_html/imes/php/login.php:10) in /home2/jzperson/public_html/imes/php/login.php on line 32
This is line 10:
<script src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
And this is line 32:
header("Location: http://imes.jzpersonal.com/userpanel.html");
Any idea why?
You probably have some output echoed out before getting to the line 32 with your header call.
See description of the header function: http://php.net/manual/en/function.header.php
Remember that 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.
Clarifications
To clarify things a little bit, the redirection using header() is performed by including a raw location response-header field to the server response. When the receiving party reads the response and sees that header field, it drops the current response and issues another request to the destination you provided.
Now, headers always come at the top (head) of the server response. That's why they are called headers! If you output any content, PHP will immediately "prefix" it with default headers and it's not possible to add any more of them after this point. So, by attempting to set another header later in your code, you get an error:
Cannot modify header information - headers already sent
By outputting HTML at line 10 you can no longer issue any more headers, because they were already sent (prefixed to your HTML output).
You can find more information about headers here: http://www.faqs.org/rfcs/rfc2616.html
Basically, you need to check whether the user is logged in or not (and redirect) before anything is sent to the browser (before HTML). Your code, then, would look something like this:
<?php
...
if($loggedIn)
{
header("Location: http://imes.jzpersonal.com/userpanel.html");
exit();
}
?>
<html>
...
<script src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
You are trying to write something before header statement
Remove any echo statements/html content before header statement. That should do the trick
You could also cheat and just use output buffering - at the very beginning of the script tree use ob_start(); to begin capturing the output. You can use headers and set cookies etc as much as you like then.
At the last line of the script tree use ob_end_flush(); to send the output. You can also grab it to a variable to further process if you wish with $buffer = ob_get_clean();
Although its not a solution as such it does allow for a more flexible coding environment AND it will solve your above problem.
Its best to flush and die if you are going to be sending a Location header:
ob_start();
/* very long snip */
header('Location: somepage.php');
ob_end_flush();
die();
This will prevent any further processing after the location change has been sent.
Just as a side note: When I speak of a script tree I mean the include path - like put the ob_start(); into a header file thats included before anything else and a footer file that flushes (and processes if required) the output buffer. Remembering, as highlighted above, that Location changes should have the script halted immediately after.
Sessions may also need to be closed with a header Location followed by a die - to use that simply
ob_start();
/* very long snip */
header('Location: somepage.php');
ob_end_flush();
session_write_close();
die();
I found that one out after hours of wondering why session data was being lost! Bear that on mind.
You can't use header(); if anything has already been sent as output. This means HTML. Do all your PHP processing first, then output your HTML/JS.
I'm learning PHP and been looking for this for a while. What I want to achieve is something like so:
if (true/false) {
go to this url;
}
Every time I search terms like php redirects or php links etc., 99% of the time I get something "headers". I read that header redirects can achieve this but no code can go before it, that it must be first on the page else it wont work.
If that's so, then how can I achieve this?
i read that header redirects can achieve this but no code can go before it. that it must be first on the page else it wont work.
That's wrong. There must be no output before this. Thus you have to ensure, that you don't echo, print, ?>something<?php (or whatever) anything before.
if (true) {
header('Location: ' . $url, false, 302);
exit; // Ensures, that there is no code _after_ the redirect executed
}
You can ready everything about it in the official manual. Especially:
Remember that 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.
echo '<script type="text/javascript"> document.location = "http://yoururl.com";</script>'
and this will be executed when this part of script is executed.
You can use this if you need some output before the redirect:
header("refresh: $time_in_seconds; url=$your_url);
You still must call this before output is actually sent however. Send the header, then send your output - the page will "redirect" in the time specified.
Disclaimer: I must admit, I'm not sure what the implications of this are and can't find docs on it, so I can't necessarily recommend it - but I can validate that it works.
I have a registration form in a site I am building. If it is filled correctly, I want the user to go back to the main page.
I tried to use header but I get "Cannot modify header information..." I guess this happens because I post to $_SERVER['PHP_SELF'];
Any suggestions of how can I redirect the user if the form is ok? (Other than a success page with a button)
You can only use the header() function if no other text/string data has been output by the web server to the users browser.
You'll need to put the logic for the redirect at the top of your script before anything else:
<?php
// Process form
// If processing was successful, redirect
if($success)
{
header("Location: http://www.main-page-url.com/");
}
?>
The reason for this is that when a browser receives information from the web server it receives an HTTP header (which the header() function outputs the redirect to), and then outputs the body of the HTTP response after the HTTP header. If your script is echoing anything before the header command, you'll continue to receive that error.
You get the cannot modify header information message because you are trying to send new headers to the browser after content has been rendered to the page. If you do the header() call before any echo/print calls, it will redirect. Otherwise, you would need a meta redirect. Where you post the form to is irrelevant.
The reason why this doesn't work is that headers precede content in an HTTP request. When you output content, PHP gets ahead of the game by sending all headers and all the content its processed thus far. There's no CTRL+Z for sending HTTP requests, so the header() function can't add headers after they've been sent.
However, you can call header() after content is echoed if you utilize the ob buffering family of functions. Call ob_start() to buffer page output, make any necessary header calls or content outputs, and finally send the output with ob_end_flush(). Ex.
<?php
ob_start(); //Start buffering
?>
<p>This is output!!!</p>
<?php
header('403 Moved Permanently'); //Fancy redirect is fancy
ob_end_flush(); //Send page content with redirect header
?>
The only possible disadvantage to using buffering is that the user will experience a slight hangup in receiving the content until the ob_end_flush() command is called. Most likely this won't be noticeable, though, so you shouldn't worry about it!
Before going through all this, you might consider moving all of your header calls to a place before content is outputted in your code. Also check the opening PHP tag for preceding spaces as they will force headers and content to be sent.
For example, here:
<?php
session_start();
if (!isset($_SESSION['is_logged_in'])) {
header("Location: login.php");
die();
}
?>
<Some HTML content>
Is die() really necessary here ?
Is die() really necessary here ?
It is: Otherwise, the client will still get the HTML code in the response body. The header asks the client to terminate and go to the new page, but it can't force it.
The client can always continue listening to the response, and receive everything output afterwards, which is a fatal security hole e.g. when protecting sensitive data in a login area.
Yes, die() is necessary. A call to header("Location: some-location.php") sends the specified header (a 302 redirect in this case) to the browser; but it DOES NOT terminate the script. It becomes more important if the lines after the redirect statement contains PHP code which may execute unintentionally. So if want to send the redirect header and abort any further processing you must call die, exit, return or any other similar construct.
Note that it is possible to perform further processing after sending the redirect header.
Yes. Simply generating a header, even the Location header, does not terminate the current script. The HTML output will be visible in e.g. a packet sniffer.
I found that: http://www.figured-it-out.com/figured-out.php?sid=181
So according to this it seems that some browsers just stop receiving the html content and redirect directly to the new page where other browsers like IE still wait untill the loading of the page is ready.
A quick question involving PHP development, I seem to be wondering about this more and more as I develop more complex sites. Basically say we have a basic PHP / XHTML inbox (messaging system). I perform checks at the top (check if user is logged in, check if user has correct permissions etc). Then use the 'header('location:www.abc.com)' function if the authentication fails. The question is do I write the rest of the inbox code in a huge 'else' block or just use standard html. I read somewhere about about it being bad to put any code after using the 'header' function.
Just follow your header with
exit();
Than it won't be a problem.
see third example here
Also you don't need a big echo like that, you can echo html like this aswell if you want:
<?php
//php stuff
if(test){
?>
html here
<?php
}
else{
?>
other html
<?php
}
?>
The reason you read it's bad, is that clients don't have to honor the Location: abc header - so if you keep sending them data they might just show it, perhaps making it possible to snoop on your users data.
What you can do, is after you send the Location: abc header, you simply exit the script, like this:
if(!$user->is_authenticated()) {
header("Location: abc");
exit();
}
After the header redirection, you put a fat "return" or "exit", so your script terminates there, then you close the if. Then you can happily code as you would normally.
It's not true that you should not put anything after a header() call. You should however remember that if you output anything before a header call, the script will fail. There are headers which require you to code on, like the Content-type header. After a redirection header, however you should always put an exit() call, in case the browser doesn't obey the instruction.
I read somewhere about about it being bad to put any code after using the 'header' function.
That's not entirely true, because it's not permitted to send output (HTML or raw output) to the browser, before you send out a header. When you DO send output before you send a header, you'll get a 'Header already sent' error.
After a header function, the rest wont be executed, so a return or exit is not required.
For the question if you need to put everything in an if/else structure: This is also not required, the only thing you have to do is a basic check if some's logged in and if not, you'll perform a redirect using the header function. No need for an extensive if/else structure.