Why doesn't this work?
output_add_rewrite_var('var', 'value');
// some links
echo '<a href="file.php">link</a>
<a href="http://example.com">link2</a>';
// a form
echo '<form action="script.php" method="post">
<input type="text" name="var2" />
</form>';
$tmp = ob_get_contents();
#print_r(ob_list_handlers());
ob_end_clean();
echo $tmp;
Taken from http://www.php.net/manual/en/function.ob-get-contents.php
I found a fix
ob_start();
ob_start();
output_add_rewrite_var('var', 'value');
// some links
echo '<a href="file.php">link</a>
<a href="http://example.com">link2</a>';
// a form
echo '<form action="script.php" method="post">
<input type="text" name="var2" />
</form>';
ob_end_flush();
$tmp = ob_get_contents();
#print_r(ob_list_handlers());
ob_end_clean();
echo $tmp;
The fix is not working
The fix is not working if I try to run it two times after each other, it works fine the first time, the last time it doesn't add the '?var=value' at all. Anyone have a clue?
As evidenced by ob_list_handlers()
in the example in the docs for output_add_rewrite_var()
, "URL-Rewriter" is an output handler. Output handlers are not run on data on the way into the buffer; output handlers are run on data on the way out of the buffer. To illustrate this, what happens if you're using the ob_gzhandler
and you grab the contents of the buffer? You don't get gz-encoded data; you get the original, uncompressed data.
From the docs for ob_start()
's output_callback
parameter:
The function will be called when the output buffer is flushed (sent) or cleaned (with ob_flush(), ob_clean() or similar function) or when the output buffer is flushed to the browser at the end of the request.
This is why your first example doesn't work. You're grabbing the contents of the buffer directly with ob_get_contents()
rather than flushing its contents, so the rewrite handler hasn't been executed.
The fix you posted is right on track. Since you have to flush the buffer for the output handler to run, you need to have another output buffer to catch the flushed data. Then that outer buffer will contain the handler-processed data, so grab its contents instead.
In regard to trying to "run it two times after each other," I see exactly what you mean. If I have a second inner buffer after the first is closed, the URL-Rewriter only works on the first. If I copy/paste and switch the order of the inner buffers, the one that works switches. It's always the one that occurs first. After playing with it for a few hours now, I'm tempted to say it's a PHP bug, unless there's an undocumented reason why it would behave that way specifically for the URL-Rewriter output handler.
To test, I wrote a simple output handler.
function ob_uppercase($buffer)
{
return strtoupper($buffer);
}
I got what I expected in terms of output handler usage.
// outer buffer
ob_start();
print_r(ob_list_handlers());
// inner buffer 1
ob_start('ob_uppercase');
print_r(ob_list_handlers());
ob_end_flush();
print_r(ob_list_handlers());
// inner buffer 2
ob_start('ob_uppercase');
print_r(ob_list_handlers());
ob_end_flush();
print_r(ob_list_handlers());
/*
Yields:
Array
(
[0] => default output handler
)
ARRAY
(
[0] => DEFAULT OUTPUT HANDLER
[1] => OB_UPPERCASE
)
Array
(
[0] => default output handler
)
ARRAY
(
[0] => DEFAULT OUTPUT HANDLER
[1] => OB_UPPERCASE
)
Array
(
[0] => default output handler
)
*/
Now if I did the same thing with the URL-Rewriter, it's not getting used in the second "inner buffer."
// outer buffer
ob_start();
print_r(ob_list_handlers());
// inner buffer 1
ob_start();
output_add_rewrite_var('var', 'value');
print_r(ob_list_handlers());
ob_end_flush();
print_r(ob_list_handlers());
// inner buffer 2
ob_start();
output_add_rewrite_var('var', 'value');
print_r(ob_list_handlers());
ob_end_flush();
print_r(ob_list_handlers());
/*
Yields:
Array
(
[0] => default output handler
)
Array
(
[0] => default output handler
[1] => URL-Rewriter
)
Array
(
[0] => default output handler
)
Array
(
[0] => default output handler
[1] => default output handler
)
Array
(
[0] => default output handler
)
*/
It doesn't matter if I use the same var name in both inner buffers or not. All uses of output_add_rewrite_var()
in the second inner buffer is completely ignored, no matter what the vars are. (I also tested with more than two, and in all cases only the first one works.)
I say it's a bug. If you agree, please submit a bug report to http://bugs.php.net .