what is the role of ob_start() in here - php

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.

Related

ob_start() without an ob_flush()

I hired someone to write an API for me in PHP and MySQL and now have to maintain it myself. I don't know php as well as other languages.
I noticed at the start of most of the php files they have:
ob_start();
I understand that this opens a new output buffer. The thing is that they never flush the buffer. The code had been working fine but I've had a lot of optimization issues, slow server responses, etc.
How is it that they don't have to flush the buffer but the response is still returning?
An example would be:
ob_start();
include "nusoap.php";
include "config.php";
require_once "class.Database.php";
$client = new nusoap_client($config['apiURL'].'/server.php',false, false, false, false, false, 600, 600);
... process the $_GET and build a $result ...
print_r($result);
Obviously the ... process ... is a wide open thing. But I'm not seeing anywhere in there that does any sort of flush or reading the ob contents. I've also searched all the includes and don't see one in there either.
I checked and implicit_flush is set to Off on this server. Since we did move this code from another server possibly on that server it was on. But still currently this API is working on this server.
The reason I said "not that I can find" when someone asked if there was an ob_get_contents() is because there are include files (including nusoap.php) that include other files and while I've grepped through them and tried to trace them, I might have missed something and am still searching. But so far it appears to my eye that no flush or get_contents is happening.
One possible answer is to say "NO, there has to either be an implicit_flush set in the php.ini file, or an implicit_flush() command somewhere, or another flush command somewhere, or getting the contents of the buffer somewhere - or the contents would never output." To me that is what the manual suggests. But sometimes there are loopholes and PHP seems to be a language of loopholes.
SOLVED
Indeed I did a simple test:
<?php
ob_start();
echo "Whats Up Doc!";
?>
and the output is seen in the browser.
PHP ob_start() function works by catching all output to buffer and then implicitly output this buffer on script end.
You may execute ob_end_clean() to discard (clean) buffer.
In Your example 'print_r($result);' will send output to buffer and then PHP interpreter will send buffer to client (http server/console).
PS. Function ob_implicit_flush() has different meaning. It just flush buffer on every output call (like print or echo), and do not have effect on script finish.

Display script result first on browser then run include file in php

I have a script that shows a result done then i call an include file to run at intervals. I would like the script result to display on browser then include file will run in the back. Right now my browser is connecting but showing nothing.I would like the browser echo Done and Logging.
<?php
ob_implicit_flush(true);
require_once('syslog.php');
$syslog = new Syslog();
$line="My msg";
$hostname = gethostname();
$ip= #$REMOTE_ADDR;
$hostnameip = GetHostByName($ip);
$syslog->Send('127.0.9.1', $hostname." ".$hostnameip." ".$line);
echo"Done";
echo "Logging......";
ob_end_flush();
include('execute.php');
?>
I believe you'll be able to get what you want by calling the flush() method right after your echo commands.
The flush() function is described as -
Flushes the write buffers of PHP and whatever backend PHP is using (CGI, a web server, etc). This attempts to push current output all the way to the browser with a few caveats.
There are some special considerations when using this function. Certain apache modules and client side buffering will still be enforced, but for now however, I do believe this will help.
Try flush() before include after last echo.

Fire-and-forget in PHP

Final update
Seems like I did make a very simple error. Since I already have a stream implementation I can just not start reading from the stream :D
I'm trying to achieve fire-and-forget like functionality in PHP.
From php.net
<?php
ignore_user_abort(true);
header("Content-Length: 4");
header("Connection: Close");
echo "abcd";
flush();
sleep(5);
echo "Text user should not see"; // because it should have terminated
?>
This works if I open the script with a browser. (shows "abcd").
But if I open it with file_get_contents or some stream library it will wait for ~5 seconds and show the second text as well.
I'm using PHP 5.2.11 / Apache 2.0
Update
I seems there is some confusion about what I'm trying to accomplish.
I don't want to hide output using output buffers (that's stupid). I want to have the client terminate before the server starts a possibly lengthy process (sleep(5)) and I don't want the client to wait for it (this is what fire-and-forget means, sort off).
The use of output buffers is merely a side effect. I've amended the sample code without the use of output buffers.
What I don't understand is: why does this script behave differently when accessing it from the browser vs. fetching it in PHP with file_get_contents("http://dev/test.php") or some stream library? What I've seen in testing is that for instance stream_get_contents will actually block for 5 seconds before it returns any output at all, the is quite the opposite of what I want.
Update2
Some more results:
The browser somehow responds to the flush(). I can't figure out how to replicate this behavior with streams in PHP, my streams keep blocking.
I've tried fread and found that it behaves similar to stream_get_contents.
Specifying a maxlength has no effect, it will still block for ~5 seconds.
Changing the blocking mode has no effect (other than generating a bunch more calls to stream_get_contents()). It will wait ~5 seconds before returning anything.
stream_set_read_buffer has no effect (tested on a PHP 5.3.5 sever)
The second portion of text is showing up because you're stopping output buffering with ob_end_flush() and ob_end_clean(). When that happens PHP outputs content as normal. Try something like the following:
<?php
ob_start(); // turn on output buffering
print "Text the user will see.";
ob_flush(); // send above output to the user and keep output buffering on
print "Text the user will never see";
ob_end_clean(); // empty the buffer and turn off output buffering. your script should end here.
?>
It's important for ob_end_clean() to appear at the end of the script. It empties the buffer and does not send its contents to the user, thus keeping everything after ob_flush() hidden.
How do you access the script using file_get_contents? How do you access it with your browser? If you access the script without "http://", of course it will never get executed. Use the same URL as in the browser.
Edit:
The browser will render the page even before the connection is closed. Even if you flush, I don't think the connection is closed. You can fire up Wireshark and check. stream_get_contents and file_get_contents will block until they have all the output. Even if you flushed, they can't be sure that there isn't more content. Since the content-length header didn't seem to make {file,stream}_get_contents return earlier, you probably need to implement your own buffering, ala. fopen, read, fclose.
Seems like I did make a very simple error. Since I already have a stream implementation I can just not start reading from the stream :D

PHP output buffering? What's the best practise?

Further to my previous question, what's the best approach when I want to buffer PHP output until I have performed all processing? I want to buffer to leave myself the option to to redirect to an error page, which I can't do after any output.
So, what's the best practise? Use a variable $output and keep appending to it, then output it at the end? Or use ob_str(), etc?
Is there a peformance to choose code-maintainability reason for one over the other? Or is it just personal preferance?
For me, I did this:
<?php
ob_start();
//do your process here
if($error)
{
ob_end_clean();
header('Location: /some/path.php');
exit;
}
ob_end_flush();
?>
I open a buffer with ob_start(); ( http://php.net/manual/en/function.ob-start.php )
Then anything that would normally be sent to the browser (except headers) is stored in the buffer until I close it. When I want to output or manipulate the buffer, I access it like this:
$buffer = ob_get_clean(); ( http://php.net/manual/en/function.ob-get-clean.php )
There are lots of other buffer options here:
http://www.php.net/manual/en/ref.outcontrol.php
This is the best way in my opinion because you don't have to keep adding items to the buffer; PHP is automatically capturing everything as long as the buffer is open.
Well written code needs no output buffering. By that I mean: first, you do all your processing, without any output. Business logic, validation, database access - this kind of stuff. After this is done, you can close the DB connection, the session, etc. because all you do is create your output based on data collected above.
This method usually results in far better maintainable code.

Browser closing and server question

How does the server knows that i've closed the browser in a code like this?
<?php
$i = 0;
while (1) {
echo "a";
flush();
$fp = fopen("$i.txt", "w");
fclose($fp);
sleep(1);
$i++;
}
?>
If i close the browser, the script stops and no more files are created.
This is because when you try to output something, such as echo "a"; flush();", PHP sees that the request has been aborted, and therefore stops the request.
Just a quick note. This only happens when you output something. I'm guessing this is because PHP was primarily used for templating, and designed mainly for outputting content. Well, if the content is not going to go anywhere, why continue processing the script?
If you don't want it to stop. Do one of the following:
Option A: Don't output anything.
flush() and echo are both considered outputs, along with many other functions. PHP only checks to see if a user has aborted when it goes to send content, so not outputting anything will make sure it doesn't check. Although that is probably not as reliable as...
Option B: use ignore_user_abort(true)
This will make sure that the script continues to output even if the user leaves the page. You can then check with connection_aborted() to find out if the connection has been aborted.
You can read all of this on PHP's Connection Handling Documentation.

Categories