Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

header() function worked, then didn't work

Status
Not open for further replies.

Mike Lewis

Programmer
Jan 10, 2003
17,509
Scotland
I have the following line of code in a script:

Code:
header('Location: maint_1.php');

This works correctly when I run the script in my development environment. But on the production server, it fails with a message saying that headers have already been sent.

I understand that this function must be executed before any output of any kind has been sent. I've taken care not to send any headers or text of any kind, not even a blank line, before calling the function. Besides, if that wasn't the case, I'd expect it to fail in both environments.

Can anyone tell me why the behaviour should be different on the two systems. The production server is running PHP 5.2.5, and the development system is 5.2.8, but I can't see anything in the change log that would affect this.

Thanks in advance.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro tips, advice, training, consultancy
Custom software for your business
 
It should also say what line sent the first output.

But apart from that, your development machine may have the buffering setting ON. In that case, output is buffered for a while and can postpone the first output enough to make a header statement work.

Also, included files may differ between the two systems.


+++ Despite being wrong in every important aspect, that is a very good analogy +++
Hex (in Darwin's Watch)
 
Maybe you are inputting something even if it doesn't look like it. You could try using ob_start() y ob_end_flush().
 
The light has gone on. I've been reading about buffering, and I can see how I might use it to solve the problem.

However, I've also discovered the cause of this particular problem: There was a comment at the top of my script.

The problem was that this was an HTML comment, not a PHP comment. So obviously it's being sent to the output stream just like any other HTML, even though it will never be visible in the browser. It's obvious now I think of it, but it didn't occur to me before.

That said, I'll consider using buffering to avoid similar problems in the future. I wish I had known about this a few weeks ago, as the buffering functions would have made it much easier for me to write my caching routines.

So, thanks again to both of you for your replies.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro tips, advice, training, consultancy
Custom software for your business
 
I've been reading about buffering, and I can see how I might use it to solve the problem.
Don't. Buffering is only useful for special things like compression. In which case you should make sure you are not counteracting your web server. It does not solve anything to switch buffering on by default. On the contrary, it causes buggy code to "suddenly" fail. Better have it fail from the very first second, so you can recall what you have done and fix it.

Don't rely on special features to "magically" repair your bugs, but solve them.


+++ Despite being wrong in every important aspect, that is a very good analogy +++
Hex (in Darwin's Watch)
 
DonQuichote,

Your point is well taken.

But are you saying that, in normal circumstances, I should never use buffering? I had the idea of using it to cache the output from a database query to a text file. This doesn't affect my original problem, which is now solved.

Basically, I've got a script that performs a slow-ish database query, which returns non-volatile data (it's only updated about once a day). Whenever a visitor requests the page in question, I check for the presence of a text file. If it is missing, or if it is more than a day old, I run the query and store the results in the file. Otherwise, I simply read in the file and echo it back to the page.

I've already written this, and it works well enough. But I was thinking that output buffering would make it simpler.

Should I use output buffering in this way, or are you saying it's better to avoid it completely?

I understand your main point - that it's better to see the bugs and fix them straight away rather than do something that might cause them to appear later. This obviously makes good sense.

Mike



__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro tips, advice, training, consultancy
Custom software for your business
 
Ah. That is not what output buffering does. Output buffering only puts all page output in a buffer. Per request, that is. So if you visit the page 3 times a day, the buffer is created 3 times and filled 3 times. And your database commands run three times. Output buffering mainly makes sense for compression between the web server and the browser. The more text is output at once, the better compression can be achieved. If PHP fails hard, output buffering may result in an incomplete output, making it very hard to see where the error is. That is why I would not use it by default.

If you want a browser to keep the results instead of re-reading the new page, you can send HTTP headers to tell the browser to cache the page. If you do not want to recalculate the page on the server, read the request from the browser (in the $_SERVER array and all starting with "HTTP_"), so you can send a HTTP header 304 - "Not modified" if it is applicable. The browser will then show the page from its own cache.

If your query is slow, it may be optimized. If you use MySQL, see the optimization chapter of the manual. If that is not possible, you may use a server-side cache, such as xcache. This is used to cache results on the server, and works along more requests.



+++ Despite being wrong in every important aspect, that is a very good analogy +++
Hex (in Darwin's Watch)
 
MikeLewis said:
Can anyone tell me why the behaviour should be different on the two systems. The production server is running PHP 5.2.5, and the development system is 5.2.8, but I can't see anything in the change log that would affect this.

Mike - it won't be anything from the delta in php versions. rather there will be something different in the setup, the php.ini file, the way that your database connection interacts or similar. something within this setup is sending data to the browser. in fact php will normally tell you what line of what script is sending the first data to the browser. which might help you get immediately to the heart of the problem.

i suspect that the delta between the setup is that your dev system may automatically turn output buffering on, thus ensuring that headers are sent before text, irrespective of when they are ordered from your script. As per the thread above, using output buffering to avoid script failures like this is not a great idea. there are times when OB is advantageous but i don't think that this is one of them.

to debug otherwise, edit the php.ini file to turn on error reporting and display. or run this scriptlet at the beginning of your script execution

Code:
error_reporting(E_ALL);
ini_set ('display_errors', true);

also make sure that you are using <?php to start your execution rather than <?. Or if you are using short tags and cannot easily change, set the php.ini directive short_open_tag to on.
 
DonQuichote,

I understand what you are saying. You've given me some interesting stuff to think about - not directly related to my original problem, but worth exploring.

One small point: I don't think the issue has anything to do with whether the database query is optimised. I would always try to write fully optimised queries, and don't have a problem with that. In this particular case, the speed of the query might not be causing a problem. It's the general idea of caching the output from a relatively show operation that I was interested in. In another case, the operation might be a call to a slow web service, for example.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro tips, advice, training, consultancy
Custom software for your business
 
Jpaide,

Thanks. That's most helpful. I'll take your advice about error reporting, and I'll try to make sure I have the same configuration on development and production (as far as possible, given I don't have much control over the production server).

In any case, my original problem is now solved, now that I have removed the comment from the top of the file.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro tips, advice, training, consultancy
Custom software for your business
 
good stuff.

in terms of caching query results, it is possible to cache them but not using OB. i would cache them in the filesystem unless they are user specific queries, in which case i would cache them via sessions. if you need more info on this, post back.
 
Jpadie,

i would cache them in the filesystem

That's exactly what I've been doing. The data changes infrequently (less than once per day), and every "query" is the same -- all users only ever see all the data for the current period.

For the first visitor each day, I save the query results in a text file. Subsequent visitors pick up that file rather than running the query again.

This is working perfectly, but at some point in the above discussion, I wondered if it would have been easier to do it with output buffering. I now realise that was a blind alley, and in any case, the app is going live next weekend, so I'm not about to start tinkering with it now.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro tips, advice, training, consultancy
Custom software for your business
 
ok.

for other readers wanting to cache data
file_get_contents() is quicker than fopen and fread
and for array type data readers might want to look at serialize and unserialize.

rudimentary cacheing script is below.

Code:
function cacheData($data){
 if (is_array($data) || is_object($data)) $data = serialize($data);
 file_put_contents ('./cache.txt', $data);
}
function restoreCache(){
 if (!file_exists('./cache.txt')) return '';
 $data = file_get_contents('./cache.txt');
 $_data = @unserialize($data);
 if (!$_data){
  return $data;
 } else {
  return $_data;
 }
}
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top