ホームページ  >  記事  >  バックエンド開発  >  PHPのバッファの機能は何ですか

PHPのバッファの機能は何ですか

爱喝马黛茶的安东尼
爱喝马黛茶的安东尼オリジナル
2019-08-28 14:49:104026ブラウズ

PHPのバッファの機能は何ですか

#バッファとは何ですか?

簡単に言うと、バッファの機能は、入力または出力の内容を、表示したり読み取ったりせずに、まずメモリに入れることです。実際、バッファの最も重要な役割は、高速 CPU と比較的低速な IO デバイス (ディスクなど) の動作を調整することです。

PHP が実行されるとき、バッファはどこで使用されますか?

PHP のバッファを理解したい場合は、PHP の実行時にバッファがどこに設定されるかを知る必要があります。

PHP を実行する際、echo print_r などのデータを出力するコードに遭遇すると、PHP は出力するデータを PHP 自身のバッファに入れて出力を待ちます。

PHP 自身のバッファは、バッファの内容を出力する命令を受けると、バッファ内のデータを Apache に出力します。Apache は、PHP が出力したデータを受け取り、データを出力します。データは、 Apache 独自のバッファを使用して出力を待ちます。

Apache が命令を受け取り、バッファの内容のみを出力したい場合、バッファの内容を出力してブラウザに返します。

ステップ: php を実行します--->(echo、print_r、その他の出力に遭遇します)、出力データを php 自体のバッファに入れ、出力を待ちます---->(出力を受信します)バッファ領域の内容) データは Apache に出力され、Apache 自身のバッファに格納されます----> (出力仕様の受信) バッファの内容は出力され、ブラウザに返されます


echo, print => ; php Output_buffering => webServer バッファ => ブラウザ buff => ブラウザ表示


つまり: スクリプト出力 => php バッファ設定 => システム バッファ設定 (Apache、nginx) => ; ブラウザのバッファ設定=> ユーザーに表示


PHP がデータを出力したいとき、2 つのバッファ (最初は独自のバッファ、次に Apache) を通過することがわかります。その後ブラウザに戻ります。


関連する推奨事項: 「

PHP 入門チュートリアル

PHP でバッファーはどのような役割を果たしますか?

1. 最も一般的なのは、ヘッダー関数を使用する前に一部のデータが出力されていることです。これにより、「ヘッダー情報を変更できません – ヘッダーは既に送信されました;

#」などの特定のエラーが発生します。 ##

echo "this is test";
header("LOCATION http://www.baidu.com");

このエラーの理由は、ヘッダーの前にいくつかのデータが出力されており、このデータの出力中に、Apache が同時にブラウザーに応答ステータスを送信することです (出力があるため、つまりこれがリクエストです)は有効です)、その後、ヘッダー関数を再度使用します。

http ヘッダーを送信すると、このエラーが返されます。このエラーは、HTTP ヘッダーが送信されたため、変更できないことを意味します。

なぜバッファを使用するとこのエラーを回避できるのでしょうか?

ヘッダー関数はバッファーの影響を受けないため、ヘッダー関数に遭遇すると、PHP はすぐに Apache を実行して、この http ヘッダーをブラウザーに送信します。

出力データ PHP が出力バッファを開いた後、データはバッファに格納され、出力を待ちます。こうすることで、以前に起こった間違いを避けることができます。

2. PHP を介してファイル ダウンロード プログラムを作成する場合。 ((例) ダウンロードを再開できる HTTP ブレークポイントを実装する PHP の方法の原理)

ファイルのダウンロードをより安全にし、制御性を向上させるために、多くの友人が PHP を使用してファイル ダウンロード ページを作成することを好みます。原理は非常に単純で、fwrite を通じてファイルの内容を読み取って表示し、ヘッダーを通じて HTTP ヘッダーを送信して、これが添付ファイルであることをブラウザーに知らせることで、ダウンロード効果を実現します。

上記の方法でダウンロード ページを提供すると、効率の問題が発生します。ファイルが大きい場合 (100M と仮定すると)、バッファ出力をオンにせずに 100M のデータをすべて読み取る必要があります。これを行うと、すべてのデータが読み取られるまでユーザーは応答を得ることができないため、ユーザー エクスペリエンスが低下します。

出力バッファが有効な場合、PHP プログラムはファイルの特定のセクションの読み取りを完了すると、すぐにそれを Apache に出力し、Apache がすぐにブラウザに戻るため、ユーザーの待ち時間が短縮されます。 。後続のデータはどうすればよいでしょうか?ファイルをピースごとに読み取る while ループを作成できます。ピースが読み取られるたびに、すべてのファイルが出力されるまですぐに出力されます。このようにして、ブラウザーはすべてのファイルが出力されるまで待つことなくデータを受信し続けることができます。ファイルが読み取られます。さらに、このアプローチは別の非常に深刻な問題も解決します。

たとえば、ファイルが 100M の場合、バッファが有効になっていない場合は、100M ファイル全体をメモリに読み込んでから出力する必要があります。しかし、PHP プログラムにメモリ制限がある場合はどうなるでしょうか?サーバーの安定性を確保するために、管理者は通常、PHP の実行メモリに制限を設定します (php.ini の totalmemory_limit を通じて、デフォルト値は 8M)。つまり、各 PHP プログラムが使用するメモリはこの値を超えることはできません。 . .値が 8M で、読み取られるファイルが 100M であると仮定すると、単にファイルを読み取るのに十分なメモリがありません。現時点では、この問題を解決するには、メモリの制限を避けるために、一度に特定の段落のみを読む上記の方法を使用する必要があります。

3.静态文件缓存

现在很多公司有这么一个需求,就是某一个页面在第一次访问的时候,会执行PHP,然后把显示的内容返回到浏览器,同时需要把这次显示的内容保存到服务器上,这样下次访问的时候,就直接把保存在服务器上的文件直接显示,而不需要通过PHP来做操作这就是所谓的”静态页面缓存”。那怎么样才能做到把内容返回到浏览器的同时把数据保存到服务器上呢?这就要用到输出缓冲区了。

ob_start();
echo 'aaa';
$string = ob_get_contents();
file_put_contents('a.html', $string);
ob_flush();
flush();

与输出缓冲区有关的配置

在PHP.INI中,有两个跟缓冲区紧密相关的配置项

1.output_buffering

该配置直接影响的是php本身的缓冲区,有3种配置参数:on/off/xK(x为某个整型数值);

on    - 开启缓冲区

off    - 关闭缓冲区

256k    - 开启缓冲区,而且当缓冲区的内容超过256k的时候,自动刷新缓冲区(把数据发送到apache);

2.implicit_flush

该配置直接影响apache的缓冲区,有2种配置参数:on/off

on - 自动刷新apache缓冲区,也就是当php发送数据到apache的缓冲区的时候,不需要等待其他指令,直接就把输出返回到浏览器。

off - 不自动刷新apache缓冲区,接受到数据后,等待刷新指令。

与缓冲区有关的函数

1.ob_implicit_flush

作用和implicit_flush一样,是否自动刷新apache的缓冲区。

2.flush

作用是发送指令到apache,让apache刷新自身的输出缓冲区。

3.ob_start

打开输出缓冲区,无论php.ini的文件如何配置,如果使用该函数,即使output_buffering设置成off,也会打开输出缓冲区

ob_start函数还接受一个参数,该参数是一个函数的回调,意思是在输入缓冲区内容之前,需要使用调用传递进来的参数把缓冲区的内容处理一次,再放入缓冲区内。

4.ob_flush

指示php本身刷新自身的缓冲区,把数据发送到apache。

5.ob_clean

清除php缓冲区里面的内容。

6.ob_end_clean

清除php缓冲区内的内容,并且关闭输出缓冲区。

7.ob_end_flush

把php自身的缓冲区里的内容发送到apache,并把清除自身缓冲区内的内容。

8.ob_get_clean

获取缓冲区的内容之后,清除缓冲区。

9.ob_get_contents

获取输出缓冲区里的内容。

10.ob_get_flush

获取缓冲区里的内容,并且把这些内容发送到apache。

11.ob_get_length

获取缓冲区里内容的长度。

12.ob_list_handlers

获取运行ob_start时,所回调的函数名称,例如:

ob_start(‘ob_gzhandler’);
print_r(ob_list_handlers);

将打印出ob_gzhandler。

13.ob_gzhandler

该函数的作用是作为ob_start的回调参数,在缓冲区刷新之前,会调用该函数对数据进行到底gzip或者deflate压缩。这个函数需要zlib扩展的支持。

使用缓冲区的相关内容

1.ob_flush和flush的次序关系。上面的分析可以看出,ob_flush是和php自身相关的,而flush操作的是apache的缓冲区,所有我们在使用这两个函数的时候,需要先执行ob_flush,再执行flush,因为我们需要先把数据从PHP上发送到apache,然后再由apache返回到浏览器。如果php还没有把数据刷新到apache,就调用了flush,则apache无任何数据返回到浏览器。

2.有的浏览器,如果接受到的字符太少,则不会把数据显示出来,例如老版的IE(必须要大于256k才显示)。这样就会造成一个疑问,明明在php和apache都进行了刷新缓冲区的操作,但是浏览器就是没有出现自己想要的数据,也许就是这个原因造成的。所以才测试的时候,可以在输出数据的后面加上多个空格,以填满数据,确定不会浏览器造成这类诡异的问题。

3.有些webserver,他自身的输出缓冲区会有一些限制,比如nginx,他有一个配置fastcgi_buffer_size 4k,就是是表明,当自身的输出缓冲区的内容达到4K才会刷新,所以为了保证内容的数据,可以添加以下代码,保证内容长度。

<?php 
echo str_repeat(" ",4096); 
?>

4.在apache中,如果你开启了mod_gzip的压缩模块,这样可能会导致你的flush函数刷新不成功,其原因是mod_gzip有自己的输出缓冲区,当php执行了flush函数,指示apache刷新输出缓冲区,但是内容需要压缩,apache就把内容输出到自身的mod_gzip模块,mod_gzip也有自身的输出缓冲区,他也不会马上输出,所以造成了内容不能马上输出。为了改善这个情况,可以关闭mod_gzip模块,或者在httpd.conf增加以下内容,以禁止压缩。

以上がPHPのバッファの機能は何ですかの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。