This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How to make PHP generate Chunked response
How can I execute something, display its contents, and continue executing it and showing its contents? I don't want to wait until the script is done to echo its content.
An example of this is on http://www.masswhois.com/. The script doesn't wait for all of the whois data to be returned before it starts showing results!
I'd recommend the following:
// .. inside of loop...
if(ob_get_length()) {
#ob_flush();
#flush();
#ob_end_flush();
}
#ob_start();
This really flushes the content to the server, but the error suppression is also useful to prevent certain configurations throwing (harmless) errors when there is nothing to flush.
Note that this doesn't necessarily prevent other server output modules from doing their own buffering, so output flushing will not be 100% fool-proof on all systems.
http://php.net/manual/en/function.flush.php
You are probably using output buffering. If you turn it off completely or use the ob_flush() you'll get what you want.
Related
Why is recommended use ob_start() in PHP language when you need include other PHP (or template) file?
This is bad:
require_once( dirname( __DIR__ ) . '/views/file.php' );
This is good:
ob_start();
require_once( dirname( __DIR__ ) . '/views/file.php' );
$output = ob_get_clean();
return $output;
But i don't get why
There is no such recommendation, use it if you think its necessary.
ob_start() tells PHP to start buffering output, any echo or other output by any means will be buffered instead of sent straight to the client.
This can be used for many purposes, one of them is being able to send headers even after producing output, since the output wasn't sent yet thanks to buffering.
In this particular piece of code you have, you are using output buffer to catch the output generated by your included file and storing it to a variable, instead of sending it to the client.
It would be hard to say without understanding a little more about your program, as well as who is telling you to do this. For one thing, the return $output line at the bottom--what are you returning from?
I can think of many reasons you'd want to include scripts this way.
In PHP, the ob_* functions deal with output buffering, that is, capturing anything that gets printed to the page/screen your PHP code is running in as a string.
This may be necessary because a very common pattern in classic PHP is to write straight HTML outside of any <?php tags. When you output text this way, it gets sent directly to the screen, bypassing any intermediate processing that you may want to do with it. It's also possible that a programmer may want to define all of their includes in one place, so that they can be switched out easily, and then reference the text to be output as a variable later in the script.
It may also be a way to prevent includes that don't output any text from accidentally outputting white space, making it impossible to change headers later on in the script. I've had problems before with a large code base in which every include had been religiously closed with a ?> and may or may not have included white space afterward. This would have solved the problem with comparatively little effort.
In programming, there are often many different ways to do things, and there's not always one of them that's "right." The end goal is to create something that does its job, is maintainable, and can be comprehended by other programmers. If you have to write a couple of extra lines of code in pursuit of maintainability, it's worth it down the line.
ob_start() is a function that begins output buffering, ob_get_clean(); flushes the buffer, and it looks like you are returning it from a function.
This allows any print or echo statements to be added to the buffer, and then all stored to a variable and returned and printed elsewhere in your application.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Everytime I create a website or application in PHP I must use the header() function to redirect people from page to page, but since the typical header is almost always sent before I find myself having to use output buffering functions that slow down the page. It's either that or suppress the "header already sent" errors. I just can't really find any example where an application can be built in PHP without having to violate either the two.
I am trying to know more, about how some redirect to pages without using output buffering.
edit
This is what some people assume is the possible.
<?php
$stack_errors = NULL;
if($_POST && isset($_POST['username']) && isset($_POST['password'])){
$stmt = $pdo->prepare('SELECT * FROM users where username = ? AND password = ?');
$stmt->execute(array($_POST['username'], $_POST['password']);
if($stmt->rowCount() == 0){
$stack_errors = 'error, username or password is incorrect';
}else{
$stack_errors = false;
}
}else{
$stack_errors = 'please enter username and password to log in';
}
if(false === $stack_errors){
header('Location: /success.php');
exit;
}
?>
<html>
<head></head>
<body>
<form>
<input ...>
<input ...>
<?php if($stack_errors){
echo $stack_errors;
}
<form>
A well-written application should not have a problem with output being sent "too early", and causing PHP to issue HTTP headers:
Firstly, decisions which might lead to a redirect should happen during processing of input and making business decisions; this code should be entirely complete before any content is output to the page. This ensures that your classes and functions have a single responsibility, and allows you - at least in theory - to replace the output without rewriting the whole application, e.g. to create a machine-readable API version. Contrary to your comments, the importance of this principle increases when you are working on larger projects.
Secondly, PHP itself might output errors and warnings, but these should be turned off on production systems using the display_errors ini setting. You don't want users seeing the gory details of every mistake in your code - at best, they'll judge it; at worst, they'll probe it for security holes.
Thirdly, others have pointed out issues with stray whitespace outside PHP tags, and Unicode BOMs added by editors. These can be tricky to track down, but by no means impossible - a decent editor will have functions to show whitespace, and to save without a BOM. Trailing whitespace can be avoided by not using a closing ?>, since it is implied at the end of a file. A small amount of output will also be swallowed if you use the gzip "output filter"; this doesn't buffer the whole output, but will buffer a few bytes at a time so it has something to compress, so gives you a bit of a get-out.
Headers are only sent when your PHP page produces output. If your file begins immediately with a <?php block (no whitespace, Unicode BOM, etc. before it), it won't produce any output before you get a chance to set your custom headers.
If your code is including/requiring any other PHP files before setting headers, make sure those files don't do any unwanted output either. Even if your include file is nothing but a big <?php block, check for whitespace/BOM at the beginning as well as whitespace at the end (such as a newline after the ?>).
Of course the header in the HTTP protocol is sent as first in the response. That's the reason it is called "header". You have to ensure in your code logic, that headers are sent before any other output. If you want to process and output any data before you make the decision which headers are to be sent, there is no other way than output buffering. PHP then does the job for you. You can flush and end output buffering as soon as you are sure that no further headers are to be sent.
According to GET parameters, I want to save the output HTML and save to my own cache. Next time it's called, load the cache. It sounds easy to use ob_start() and ob_get_contents() but what if the other running scripts in between use this too? It spoils the "original" output buffering, right?
How to globally save the output?
To quote the PHP manual for ob_start:
Output buffers are stackable, that is, you may call ob_start() while
another ob_start() is active. Just make sure that you call
ob_end_flush() the appropriate number of times.
In other words: No, it doesn't spoil the original output buffering; buffering can be nested. You can also use ob_get_flush() instead of ob_end_flush() to "stop" buffering.
I hope everyone's holidays are going well.
Another PHP related question here. I am using output buffers in my script, for what I have recently learned is an invalid reason (so I can pass headers later in the script). I now realize that I should be storing all output in a variable or some other sort of storage until I am ready to output at the end of the script instead of using output buffers. Unfortunately, I have already coding these functions and the spontaneous output of html into my pages already. I was hoping to be able to fix this problem in version 2 of the script, as I have strict deadlines to meet with this version.
To the question at hand. I was planning to do this, but apparently die() and exit() functions do not work so well with output buffers? I have exit() after all of my error messages, and instead of ending the execution at that point, it seems the script keeps going due to the output buffer. I have tested this hypothesis by removing the output buffers and the exit() functions work as expected.
Is there a way I change this behaviour, or should I go back to the drawing board and begin replacing my older pages? Also, can someone please explain to me why we should keep output till the end? I'm always interested in learning.
Thanks in advance everyone! Enjoy the last few days of 2010!
While I'll leave the headier and more abstract questions to more intelligent minds than I, I would recommend that you create a wrapper exit() function to simplify the code when you have errors.
i.e-
if(!$good)
{
trigger_error('bleh', E_USER_WARNING);
errorExit();
}
function errorExit()
{
ob_flush();
exit();
}
And replace all your exits with that function call and that way the buffer is flushed and the program will exit at the proper time.
Difference between header and the actual page content is basically only the position where they occur.
As the name suggests, header is in the beginning of the output. After that two carriage/returns (enter symbols) are sent and everything after that is presumed to be content.
Therefore, if you echo something and then want to change the header, it cannot be done. The content part already closed header part. What you would send as new header would now display as plain text (should PHP interpreter not stop you, which it does).
As for the other part of the question, ob_flush is a good solution as noted by Patrick.
This question already has answers here:
How to fix "Headers already sent" error in PHP
(11 answers)
Closed 9 years ago.
I'm looking for things that might trigger the following PHP warning:
PHP Warning: Cannot modify header
information - headers already sent in
Unknown on line 0
Turned out that it was the line
ob_start("ob_gzhandler");
that caused the warning. This has been reported and fixed in 2001, it seems, but for some reason it keeps coming back.
It might be a lot of things, but as the others said, it's often just a space lying around somewhere that gets outputted and then a header() command is sent which normally is fine, but not after starting to send content back (potentially just a space in this case).
Using ob_start() stops the output from going out right away by buffering it. So it's a potential solution, or at least way to diagnose where it's coming from as zodeus said.
One common thing that causes those lose spaces are in this scenario.
global.php
<?php
$variable = 1;
$database = 'something else';
?> <-- A space here
<-- Or here
index.php
<?php
require('global.php');
$var = dosomething();
header('Location: http://www.example.com/');
?>
One way to fix that is to remove the ?> at the end of the global.php file. You don't need those, they are only useful if you start putting HTML for example after your PHP code. So you'd have:
<?php
$variable = 1;
$database = 'something else';
And when you do the require(), the space is not outputted before the header().
Just to illustrate the problems with content outputted and headers is that other common case that gives a similar error. It happens when you forget to stop the processing after a redirection using header().
if ($notLoggedIn) {
header('Location: http://www.example.com/login.php');
}
echo 'Welcome to my website'; // this will be outputted,
// you should have an exit()
// right after the header()
I think whats happening is one of the built in php functions is outputting something. I've seen this with a couple of the IMAP functions where they out put just a " " (space character) and it screws things up.
You can thry tracking it down using Xdebug or the Zend debugger, but i f you have neither
try wrapping output buffering around some of the functions you think may be cause it.
ob_start();
callYourFunction();
ob_end_clean();
Do this one function at a time and when the error goes away you'll know which function is cause you the problem, then you can either file a bug report or just leave it in as a hack. But at least then you know what function is cause the issue.
Edit: The fact that is says your output is occurring on line 0 means that it's a C level function doing the output, not any code that's been written using PHP.
Have you checked your files for unintended UTF-8 BOMs?
The error tells you that something has sent output, which would force headers to be sent, because the headers must be written before the body of the http message.
The most common problem I have found is text in headers. vis:
<?php // myfile.php
include 'header.php';
?>
and in header.php:
<?php // header.php
....
?>
What you can't see here is that there is a blank - either a space or CR/LF after the closing '?>'. This is output because the php standard says that anything outside the php tags is output as html.
The solution is to make sure that you make sure to erase everything after the closing '?>'