Warning: Cannot modify header information - headers already sent
first off, i'm not sure if this is the correct subforum to submit this problem; apologies if it isn't.
The problem is:
Quote:
Warning: Cannot modify header information - headers already sent by (output started at C:\xampp\htdocs\include\php_layout\admin_suite\header.php:45) in C:\xampp\htdocs\admin\admin_webmasterqueries.php on line 166
admin_suite\header.php:
PHP Code:
include("../include/session.php");
if(!$session->isAdmin()){header("Location: ../game/index.php"); exit;}
else{ //Display everything below if user is not logged in
include("../include/php_layout/admin_suite/header.php"); //header
line 166 in delete function:
PHP Code:
//code executes if admin decides to delete query
if($id == "delete" && $status == "delete") {
//Added for furthur security measures - [Second check that user is authorised]
if(!$session->isAdmin()){header("Location: ../game/index.php");}else{
$query_id = $_GET['queryID']; //Gets the querie's ID
$q = "DELETE FROM contactwebmaster_requests WHERE wmqueryID='$query_id' LIMIT 1";
$query_delete = $database->query($q) or die("MySQL error: ".mysql_error());;
header("Location:".$session->referrer."");}
}//if ID=delete
line 166 being:
Quote:
header("Location:".$session->referrer."");}
I can't seem to figure out why its saying headers have already been sent? Any help would be seriously appreciated
Last edited by CallumJohnson; 02-17-2010 at 12:33 PM..
Reason: resolved
$query_id = $_GET['queryID']; //Gets the querie's ID $q = "DELETE FROM ".TBL_WMQUERIES." WHERE wmqueryID ='$query_id' LIMIT 1"; $database->query($q) or die("MySQL error: ".mysql_error()); ob_flush(); }//if ID=delete
Do you have any output before your header calls? Are you calling any echos. Do you have a blank line at the top of your file? Have you checked to see if you have a BOM at the top of your file? A BOM is usually in invisible character that some editors put into code but you don't notice it.
__________________
||||If you are getting paid to do a job, don't ask for help on it!||||
Some output has been sent to the browser before line 166. Even if you e.g. have a space before <?php at the start of the file this error would happen. Or some echo has been done before header(). Or some error message has been sent to the output stream as Angst correctly said.
Absolutely any output sent to the browser means the HTTP server has been forced to send some default HTTP headers and now sending the page body.
The good solution is to find which part of your script is sending some output before using header() and correct that.
The worse solution is to use Output Buffering functions.
Edit: _Aerospace_Eng_ has been a few seconds faster.
The question is very common. And most PHP forums have a sticky for this. The CF PHP forum in not an exception. Please look at it and ask questions if you do not understand something.
it seems i had a BOM but this line is throwing the header error too: <?php
if($session->isAdmin()){echo '"http://localhost/admin/admin_mailinbox.php"';}
Is your header before that line or after that line? If its after then yes it will throw the error because you use echo which is sending output to the browser. We need to see the exact error and you need to post all of your code.
__________________
||||If you are getting paid to do a job, don't ask for help on it!||||
include("../include/session.php"); if(!$session->isAdmin()){header("Location: ../game/index.php"); exit;} else{ //Display everything below if user is not admin include("../include/php_layout/admin_suite/header.php"); //header
//This next bit is for administrators to //view any help-desk submissions if(!isset($_GET['id'])) { $id = $_GET['id']; $user = $session->username;
$q_unread = "SELECT * FROM ".TBL_WMQUERIES." ORDER BY wmqueryStatus='unread' DESC"; $query_unread = $database->query($q_unread) or die(mysql_error());
if(mysql_num_rows($query_unread) == 0){$q = "SELECT * FROM ".TBL_WMQUERIES." ORDER BY Timestamp DESC";} else {$q = "SELECT * FROM ".TBL_WMQUERIES." ORDER BY wmqueryStatus='unread' DESC";}
$getquery = $database->query($q) or die(mysql_error());
//Updates database that the submission has been read by a moderator $q = "UPDATE ".TBL_WMQUERIES." SET wmqueryStatus='read' WHERE wmqueryID='$query_id'"; $database->query($q) or die("MySQL error: ".mysql_error());
//code executes if admin decides to delete query if($id == "delete" && $status == "delete" && $session->isAdmin()) { ob_start();header("Location:".$session->referrer.""); //UNRESOLVEDISSUE
$query_id = $_GET['queryID']; //Gets the querie's ID $q = "DELETE FROM ".TBL_WMQUERIES." WHERE wmqueryID ='$query_id' LIMIT 1"; $database->query($q) or die("MySQL error: ".mysql_error()); ob_flush(); }//if ID=delete
//code executes if admin decides to delete query if($id == "reply" && $status == "responce" && $session->isAdmin()) {
$query_id = $_GET['queryID']; //Gets the querie's ID $q = "DELETE FROM ".TBL_WMQUERIES." WHERE wmqueryI ='$query_id' LIMIT 1"; $database->query($q) or die("MySQL error: ".mysql_error()); //header("Location:".$session->referrer.""); //UNRESOLVEDISSUE
}//if ID=delete
//Layout codes for bottom container (ID=view or delete or reply) echo'</div> <div id="main_cont_bottombg_viewquery"> <div id="main_cont_bottombg_left"></div> <div id="main_cont_bottombg_right"></div> </div></div>
function confirmation(wmqueryID) { var answer = confirm("Delete this submitted query?") if (answer==true){ window.location = "?id=delete&queryID="+wmqueryID+"&status=delete"; return true; } else{ return false; } }
//navigation bar var timeout = 500; var closetimer = 0; var ddmenuitem = 0;
// open hidden layer function mopen(id){ // cancel close timer mcancelclosetime(); // close old layer if(ddmenuitem) ddmenuitem.style.visibility = 'hidden';
// get new layer and show it ddmenuitem = document.getElementById(id); ddmenuitem.style.visibility = 'visible';} // close showed layer function mclose(){ if(ddmenuitem) ddmenuitem.style.visibility = 'hidden';}
// go close timer function mclosetime(){ closetimer = window.setTimeout(mclose, timeout);}
// cancel close timer function mcancelclosetime(){ if(closetimer){ window.clearTimeout(closetimer); closetimer = null;} } // close layer when click-out document.onclick = mclose; //--></script> </head><body> <div id="center_container"> <table width="862" cellpadding="0" cellspacing="0" border="0"> <tr> <td id="Site header" colspan="2" class="site_header_tblcss">
Error message: Warning: Cannot modify header information - headers already sent by (output started at C:\xampp\htdocs\include\php_layout\admin_suite\header.php:71) in C:\xampp\htdocs\admin\admin_webmasterqueries.php on line 164
error generated when: ?id=delete&queryID=[a number corresponding to query id]&status=delete
i didn't post all of my code originally because theres loads of it
If you have posted that correctly and "output started at C:\xampp\htdocs\include\php_layout\admin_suite\header.php:71" then I asusme there is some output buffering somewhere, because output should have started at line 1 of header.php?
Anyway the point is you are trying to a redirect
PHP Code:
header("Location:".$session->referrer."")
but you have already sent output to the browser from the header.php file you included at the top. You either need to move your redirect logic above all output or start output buffering at the top with ob_start() so that nothing actually goes to the browser until you have decided if you are going to send a redirect.
Brief reason:
HTTP reponse look like
header
header
header
content
content
content
content
with the first blank line indicating end of headers. Therefore before you send any content the headers have to be sent. Therefore as soon as the first content is sent PHP puts out all currently set headers and once that is done there is no way to "retrofit" a new header such as "location:". By enabling output buffering nothing is sent to the browser until you tell it to or the script exits (default behaviour sends content in chunks as it is generated) and therefore PHP can insert more headers into the top of the response right up until the content is sent.
It is not really good practice to use ob_start() as a means to avoid issues like this as it could mask other issues, prevent you from controlling output as you want elsewhere etc.
The "better" option as Aerospace suggest is to rearrange the code so that there is no output until you know whether you want it or not.
That said, if you want to minimise refactoring and are prepared to accept the small risk that it may confuse you or other developers at some point in the future, I can't see any real problem with it, just lazy/bad/impure/whatever.
In other words an experienced developer with the time to do the job properly would refactor the code to avoid it, a less experienced developer and/or one who just needs to get it working now would not