This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Headers already sent by PHP
My problem is that I have a class with a function inside of it, and I get;
Warning: Cannot modify header information - headers already sent by (output started at /home/user/public_html/inc/class.php:105) in /home/user/public_html/inc/facebook/login.php on line 21
When the page I'm using it on redirects a user with the header(); tag. The class is;
class mysql {
private $user;
private $pass;
private $db;
public function __construct($user1, $pass1, $db1) {
$this->user = $user1;
$this->pass = $pass1;
$this->db = $db1;
$this->connect();
}
public function connect() {
$this->connection = mysql_connect('localhost', $this->user, $this->pass);
$select = mysql_select_db($this->db, $this->connection);
}
public function query($x) {
return mysql_query($x);
}
public function fetch($x) {
return mysql_fetch_array($x);
}
public function num($x) {
return mysql_num_rows($x);
}
}
Line 105 is the;
return mysql_fetch_array($x);
And the file trying to do the header redirect just includes this file at the top of the page and does the header lower down.
Thanks in advance.
What is triggering this error?
This error is triggered when some code has already output to the "screen" before you call the header function. Headers must be set before you output anything.
See the description from the header() PHP manual page:
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.
I am not outputting anything so what gives?
I would say that your code is generating an error somewhere. Try setting:
ini_set('display_errors', true);
ini_set('error_reporting', ~0);
In your index.php file as the very first set of commands.
Another possibility is that something somewhere is outputting a space or line return character. You cannot have any output of any kind before you call the header() function.
Possible solutions
There are two ways to fix this.
Use output buffering to catch anything that might be echoed before you have set your headers
Stop the code from outputting anything prematurely although this is a little more brittle
Option 1
To implement solution 1 you would put a call to ob_start() at the very beginning of your code (at the top of your bootstrap file or index.php usually).
Then once all logic has been completed and you are ready to output you would call ob_end_flush() to output everything in the buffer. Usually this would be at the very end of your index.php or bootstrap file.
Option 2
Zend Framework has the following in their coding guidelines to help mitigate the accidental output of new lines and spaces. See http://framework.zend.com/manual/en/coding-standard.php-file-formatting.html#coding-standard.php-file-formatting.general:
For files that contain only PHP code, the closing tag ("?>") is never permitted. It is not required by PHP, and omitting it´ prevents the accidental injection of trailing white space into the response.
When the page I'm using it on redirects a user with the header(); tag. The class is;
That's the problem. You need to put ob_start(); right at the beginning of the file with header();.
That line shouldn't output anything, so that means that output was started because a warning or notice was printed. Fix the problem.
Alternatively, you gave use the wrong source file.
Disable wanrings on php.ini .Those are warnings , if you have access in your php.ini , modify the following
error_reporting = E_ALL & ~E_NOTICE & ~E_DEPRECATED
when in development
display_errors = On
when you'll be in production don't forget to
display_errors = Off
Don't forget to restart apache when you change php.ini
I didn't say to disable errors ,disable only warnings,
Cannot modify header information means you have outputed something before the header.remove all spaces before header();
Related
I am fairly new to PHP, even more so to the ob_ functions, so help me understand this, as the manual is somehow does not provide a very simple example or reference.
I am assuming that "output buffering" is what delays and holds php from sending headers until full content is sent, and that may be why the header() function does not issue an error if ob_start() is declared above. If so, my question is how do I "buffer" only some contents instead of just mentioning ob_start() at the top of my script, which is greatly slowing down my application?
Example.
<?php
namespace App\Controller;
class Home extends Controller{
public function showHomePage()
{
$students = $pdo->query('SELECT id FROM students');
$view->showContent($students); // includes content.php
}
}
//content.php
<p> showing stundent by id </p>
<?php
showContent()
{
if(!$students){
header('Location: /404');
}else{
//show students
}
}
}
Now you can see in the above example that, as soon as content.php is loaded, it will issue header already sent sent error (if $students evaluates to false/null ) so, to hide this error, I placed ob_start() inside my howHomePage method as seen here
public function showHomePage()
{
$students = $pdo->query('SELECT id FROM students');
ob_start();
$view->showContent($students); // includes content.php
}
Now, with the above approach, I get no header errors, but I would like to close that buffer as soon as the showContent() method is executed. In other means, I don't want the ob_start() to apply only for that following function. I tried to do something like this
public function showHomePage()
{
$students = $pdo->query('SELECT id FROM students');
ob_start();
$view->showContent($students); // includes content.php
on_end_flush();
}
but now, the contents showContent() are not being shown
<p> showing stundent by id </p>
<?php
showContent()
{
if(!$students){
header('Location: /404');
}else{
//show students
}
}
}
This is a terrible way to code. You've already got your output baked in, which, as you've noted, prevents you from changing the header(). This is a major driver behind MVC, which holds that you need to segment your code and separate your view(HTML) from your controller(PHP). In this case, you've put a function inline with your HTML.
There's a couple of ways to work around this without having to resort to output buffering
Do the check on $students earlier in the page (like when you get/build the data set) and issue the 404 there.
Move your HTML into a separate template file (maybe check out Smarty to help with that) and then do your drawing there.
I had the same issue and solved it by adding:
ob_implicit_flush(true);
to the beginning of the php file. This outputs everything right away and you can take your other flush commands out.
http://php.net/manual/en/function.ob-implicit-flush.php
ob_implicit_flush() will turn implicit flushing on or off. Implicit
flushing will result in a flush operation after every output call, so
that explicit calls to flush() will no longer be needed.
Does any body has any idea how to find where the leak is that provokes this "Content Encoding Error" with $config['compress_output'] = true in CodeIgniter?
I've trying to debug this error for days, but I can't seem to find where the leak is. LogLevel is at debug but I see no info in the log when this error happens.
So, any ideas how to debug this?
UPDATE
I really don't want to disable the compress_output feature, I just want to see how can I trace where the error is produced
UPDATE2
I've looked over and over again to see if there is any output in the controllers... and there is none, so some where else must be the error provoked. No models/database, just controllers, libraries, helpers and views
This issue is where the output buffering starts. The check for the config variable is in system/core/Output.php in _display(). It starts the gzipped buffering after a lot of code has already run. This leaves the potential for output to have occurred before it buffering starts.
With compress_output set to false it doesn't matter because nothing is encoded. With it set to true you end up with mixed content. Some output is encoded and some is not which causes the compression error.
There are two solutions:
1) You could leave compress_output set to false and add ob_start('ob_gzhandler'); to the top of your index.php file. This will ensure that all output is always gzipped, including errors.
2) The other solution is to add ob_flush(); before ob_start('ob_gzhandler'); in system/Output.php. This will gzip output when there are no errors and serve you unencoded content when there are errors.
I think 2 is the better solution and should be implemented by the CodeIgniter team. But if you don't want to muck with the system code (changes will go away when you upgrade) then 1 is the better solution for you.
This might be a long shot, but if you echo/print database output directly from your controller instead of sending it to the model you'll likely get error messages that have to do with output buffering. Are you echoing from your controller?
Putting the following line in config.php:
$config['compress_output'] = FALSE;
Solves it. The problem in my case was that I sent the post, but it did not recognize the FILLCATEGORIAS function. Inly by changing the $ config [ 'compress_output'] = FALSE; solved it.
THIS problem occurred when we send data using a POST request:
Failed to load resource: net::ERR_CONTENT_DECODING_FAILED
<script type="text/javascript">
$(document).ready(function() {
$("#idEmpresa").change(function() {
$("#idEmpresa option:selected").each(function() {
id = $('#idEmpresa').val();
$.post("<?php echo base_url();?>Admin/fillCategorias", {
idEmpresa : id
}, function(data) {
$("#idCategoria").html(data);
});
});
});
});
</script>
Any error in PHP will break compression.
To test this, in index.php change:
error_reporting(E_ALL);
to
error_reporting(E_ALL ^ E_NOTICE);
Do not echo/print to display output from controller.
Do not use "?>" at the end of controller file.
I hope it helps.
Update:
To check if the output is empty before starting buffering, you can open core/Output.php and add
ob_flush();
before
ob_start('ob_gzhandler');
If there is even a space or an empty line, compression will fail. (check page source from browser). This happens because with $config[‘compress_output’] = true , ob_start('ob_gzhandler') (line 379 in Output.php) is executed, wich will cause a "Cannot modify header information - Headers already sent ..." warning. This warning is the cause of compression failure.
So basically, any echo outside of Output class (json output included) will send headers to client, which will cause "Cannot modify header information - Headers already sent ..." warning, which will cause the "content encoding error".
I had the same problem. After searching, I found that my controller has ?> at end of file. So I removed it and it works perfectly. Here is a link for more detail.
More compliant solution:
$this->output->set_output($data);
Some CPanel lightspeed extension updates create this problem. You can try adding this code in your .htaccess file:
php_flag zlib.output_compression ON
I have a function, 'redirect_to()' written on php script that is called after a successful update to a page on my custom CMS. It works fine on the localhost, but when I try it on my actual live domain I get the following error message:
Warning: Cannot modify header information - headers already sent by (output started at /hermes/bosweb/web119/b1192/ipg.typaldosnetcom/edit_listing.php:7) in /hermes/bosweb/web119/b1192/ipg.typaldosnetcom/includes/functions.php on line 20
Here is the code for the redirect_to() function:
function redirect_to ($location = NULL) {
if ($location != NULL) {
header("Location: {$location}");
exit;
}
}
I've made sure to call the function before I output any HTML, so I'm not sure what the problem really is.
My question: Why am I receiving this error?
It's not lying. You've output something before getting to this point. Check the locations mentioned in the error messages.
Show us the first 25 lines of each of the files mentioned.
you already sent your output to the page before you set the header. first you need to set the headers and then can the output come.
It can even be a whitespace.
It means something was already outputted on the suggested line. Try going there and see what it does.
Try pasting the surrounding code on that position for a better clarification if you can't find the problem yourself.
One common cause is to have a line after a php file you're including...
Simple solution: remove the closing php tag "?>" from all files as it's not needed..
You can test if you have a character before the opening php-script tag by removing any closing php-script tag. This way you are sure there isn't any character left (it's not needed).
Use output buffering:
<?php
ob_start();
// Test buffered output.
echo 'hello world';
function redirect_to ($location = NULL) {
if ($location != NULL) {
header('Location: ' . $location);
exit;
}
}
// rest of php file here
ob_end_flush();
?>
Docs: ob_start() and ob_end_flush()
session_start();
ob_start();
$hasDB = false;
$server = 'localhost';
$user = 'user';
$pass = 'pass';
$db = 'acl_test';
$link = mysql_connect($server,$user,$pass);
if (!is_resource($link)) {
$hasDB = false;
die("Could not connect to the MySQL server at localhost.");
} else {
$hasDB = true;
mysql_select_db($db);
}
a) what does ob_start() exactly do.? i got to understand it will turn output buffering on. with reference to the above code what will be the benefit if i use ob_start() while trying to establish the connection with the database. what output data it will buffer?
thank you..
Normally php sends all text not included in <?php ... ?>, all echos, all prints to the output. Which is send to the err... output: http server (which sends it to a client), console etc.
After ob_start this output is saved in output buffer, so you can later decide what to do with it.
It doesn't affect db connection. It deals with text (mostly) produced by php.
Some PHP programmers put ob_start() on the first line of all of their code*, and I'm pretty certain that's what going on here.
It means if they get halfway through outputting the page and decide there's an error, they can clear the buffer and output an error page instead. It also means you never get "couldn't sent headers, output already started" errors when trying to send HTTP headers.
There are a few legitimate reasons to do this, but I'd take it as a sign that they are mediocre programmers who don't want to structure their code in a coherent order - i.e. they should be working out if there are errors or headers to send before they start rendering the page. Don't copy this habit.
(* What makes this an easy habit to fall into is that if output buffering is still turned on when the script end is reached, the buffer is sent to the user, so they don't need to worry about a matching end statement)
first of all buffering is usefull for putting http-headers (header function) at any line of code. eg - session cookies. without ob_start you would not be able to add any http-header to response if you already sent some data, e.g. with echo or print functions
In this particular code ob_start seems useless. The benefit of output buffering is in either following code or does not exist. `In general, consult PHP manual about ob_start.
I'm having some problems with the output buffer. I am buffering my script and printing the result using a callback. The problem is that if a error is thrown at any point, nothing is being shown and I am getting a blank screen. I have tried setting my own custom error handlers but nothing seems to work. I have a feeling this is because the errors are causing my buffer to call the callback method instead of my error handler. Either that or it's because I have the error handler as a static method, but changing that causes issues elsewhere.
I'd really appreciate any help because this one has me stumped!
public function constructor()
{
ob_start(array(__CLASS__, 'render'));
self::$buffer_level = ob_get_level();
set_error_handler(array(__CLASS__, 'exception_handler'));
set_exception_handler(array(_CLASS__, 'exception_handler'));
RUNNING MY SCRIPT HERE
ob_end_flush();
}
public static function exception_handler($exception, $message = NULL, $file = NULL, $line = NULL)
{
while (ob_get_level() > self::$buffer_level)
{
ob_end_clean();
}
echo $exception.' - '.$message.' - '.$file.' - '.$line.'<br/>';
}
I would suggest turning on error logging in PHP which will send errors to the apache error log by default. You could also try turning on track_errors, but I think the log is the best bet. If you don't have access to the apache log, you might have to log things manually.
Log files and tracing strategies are essential when using output buffering and other "behind the scenes" stuff (like ajax).
You might also have a look at the output_buffering setting. See this article: http://thinkpositivesoftware.blogspot.com/2009/03/have-blank-php-page.html