[wp-hackers] Replace default doctype on one page only through
plugin
Gaarai
gaarai at gaarai.com
Mon Jan 19 13:01:44 GMT 2009
I've never seen that entry in the documentation. I just didn't
understand how they could nest as there is nothing to separate one
grouping of ob_start/ob_end_flush and another grouping. So, if ob_start
calls do nest, how do the ob_get_contents calls know which level of
contents to get, the first or the second?
Thinking about it more (since I was really tired when I made that
response last night), I suppose it's possible that it forces nesting by
using a stack. Thus, if I call ob_start, ob_start, $a = ob_get_contents,
ob_end_flush, $b = ob_get_contents, ob_end_flush, $a will only contain
the buffer from the most-recent ob_start call while $b contains the
output buffer that was essentially on the stack and returned to the top
when ob_end_flush was first called.
I still think that this is a bad idea though. Since the code I provided
has such a huge gap between the ob_start and ob_end_flush calls, it's
also possible for someone else to do this. Imagine that this theoretical
code also latches into the wp_head action, is called before my
send_output function, and calls ob_start. Now also imagine that this
code does not call ob_end_flush until the shutdown action. Now we have
mismatched nesting. There really isn't a way to prevent such issues as
you can never know what code may interact with your code at some point
down the line.
My stance remains that using ob_start in this manner is dangerous and
adds a definitive point-of-failure to the code. So, my conclusion last
night was correct, but the reason for it being correct was off a bit.
Now if ob_start somehow adopted a naming convention like an object model
rather than being based off of a stack model, this could work. For
example, imagine the following:
<?php
if ( $contact_page_displayed ) {
add_action( 'get_header', 'start_output_collection', 1000 );
add_action( 'wp_head', 'send_output', 1000 );
}
function start_output_collection() {
global $my_header_output_buffer;
$my_header_output_buffer = ob_start();
}
function send_output() {
global $my_header_output_buffer;
if ( false !== $my_header_output_buffer ) {
$header = ob_get_contents( $my_header_output_buffer );
if ( false === $header )
die( 'send_output() failed to retrieve header output
buffer. File: ' . __FILE__ . ' on line: ' . __LINE__ );
if ( false === ob_end_clean( $my_header_output_buffer ) )
error_log( 'send_output() received a failure when
trying to remove an output buffer. File: ' . __FILE__ . ' on line: '
. __LINE__ );
$header = preg_replace( '|<!DOCTYPE[^>]*>|i',
'<!DOCTYPE..>', $header );
echo $header;
}
?>
If such a mechanism as I've coded here could exist, then I would say
that using ob_start for such applications would be viable. However, this
is not the case, thus ob_start is still dangerous to use except in very
tight sections of code where random code couldn't wander in and ruin the
party.
For anyone reading this, the code above is theoretical code and won't
function. I know, I tested it. Besides, it's based off of a premise of
how code could function if specific PHP functions worked in a different
manner. In other words, don't use it.
Chris Jean
http://gaarai.com/
http://wp-roadmap.com/
Mike Schinkel wrote:
> Gaarai <gaarai at gaarai.com> wrote:
>
>> The problem is that the ob_start function does not nest. There is no
>> way to guarantee that nothing else will call ob_start between the
>> start_output_collection() and send_output() functions. On a standard
>> install with the default theme, there are a total of 45 apply_filters
>> calls as well as requiring the theme's header.php code. At any point
>> in executing an of these sections of code, some code may exist that
>> makes use of ob_start.
>>
>
> I'm confused. According to PHP.NET[1]:
>
> 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. If multiple output
> callback functions are active, output is being filtered sequentially
> through each of them in nesting order.
>
> And this[2] explicitly says you can nest calls. Obviously, I'm missing something as your statement and PHP.NET seem to contradict. I'm sure it's my misunderstanding; I've been coding for 20 years but only PHP for two and only recently on a hard-core basis so I haven't learned all it's ins-and-outs of PHP. So I'm hoping you can help me better understand this apparent dichotomy.
>
> TIA.
>
> -Mike Schinkel
> http://mikeschinkel.com/custom-wordpress-plugins/
>
> [1] http://us3.php.net/ob_start
> [2] http://www.codewalkers.com/c/a/Miscellaneous/PHP-Output-Buffering/1/
>
>
> _______________________________________________
> wp-hackers mailing list
> wp-hackers at lists.automattic.com
> http://lists.automattic.com/mailman/listinfo/wp-hackers
>
>
More information about the wp-hackers
mailing list