なぜうまくいかないのか
のドキュメントの例で示されob_list_handlers()
ているように、「URL-Rewriter」は出力ハンドラーです。出力ハンドラーは、バッファーに入る途中のデータに対しては実行されません。出力ハンドラーは、バッファーから出る途中のデータに対して実行されます。これを説明するために、を使用していて、バッファの内容を取得するとどうなりますか?gzでエンコードされたデータは取得しません。元の非圧縮データを取得します。output_add_rewrite_var()
ob_gzhandler
のパラメータのドキュメントob_start()
output_callback
から:
この関数は、出力バッファーがフラッシュ(送信)またはクリーンアップされたとき(ob_flush()、ob_clean()または同様の関数を使用)、または要求の最後に出力バッファーがブラウザーにフラッシュされたときに呼び出されます。
これが、最初の例が機能しない理由です。バッファの内容をob_get_contents()
フラッシュするのではなく、で直接取得しているため、書き換えハンドラは実行されていません。
修正が機能する理由
あなたが投稿した修正は順調に進んでいます。出力ハンドラーを実行するにはバッファーをフラッシュする必要があるため、フラッシュされたデータをキャッチするために別の出力バッファーが必要です。次に、その外部バッファーにはハンドラー処理されたデータが含まれるため、代わりにその内容を取得します。
複数の連続したバッファに関する問題
「2回続けて実行する」ということに関しては、まさにその意味がわかります。最初のバッファが閉じられた後に2番目の内部バッファがある場合、URLリライタは最初のバッファでのみ機能します。内部バッファのコピー/貼り付けと順序を切り替えると、機能するバッファが切り替わります。それは常に最初に発生するものです。数時間遊んだ後、それがPHPのバグであると言いたくなります。ただし、URLリライター出力ハンドラーに対して特にそのように動作する理由が文書化されていない場合を除きます。
テストするために、簡単な出力ハンドラーを作成しました。
function ob_uppercase($buffer)
{
return strtoupper($buffer);
}
出力ハンドラーの使用に関して期待したものが得られました。
// 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
)
*/
URLリライタで同じことをした場合、2番目の「内部バッファ」では使用されません。
// 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
)
*/
両方の内部バッファーで同じ変数名を使用するかどうかは関係ありません。output_add_rewrite_var()
変数が何であっても、2番目の内部バッファーでのの使用はすべて完全に無視されます。(私も2つ以上でテストしましたが、すべての場合で最初の1つだけが機能します。)
バグだと思います。同意する場合は、バグレポートをhttp://bugs.php.netに送信してください。