CLIII. ストリーム関数

導入

ストリームは、PHP 4.3.0 に、 ファイル、ネットワーク、データ圧縮などに関する、 共通した一連の関数群と利用法を持つ操作の一般化の手法として 導入されました。もっとも単純な定義では、ストリーム というのは、ストリーミング可能な動作を体現する resource オブジェクトといえます。つまり、ストリームには線的に読み出したり、 あるいは書き込んだりすることが可能で、かつ、 ストリーム上の任意の場所に fseek() できる場合も あります。

ラッパー というのは、ストリームにおいてどのように特定の プロトコル/エンコーディングを扱うかを扱うかを指示する付加的なコード です。たとえば、http ラッパーは、どのようにして URL を、リモートサーバのファイルに対する HTTP/1.0 リクエストに転換するかを知っています。PHP には、デフォルトで組み込まれているラッパーが多数存在しますが (付録M を参照ください)、 それに加え、カスタムラッパーをstream_wrapper_register() を利用して PHP スクリプトの内部から、あるいはストリーム API を用いて、 直接拡張モジュールの内部から追加できます。 (ストリーム API については 第44章 を参照ください) あらゆる種類のラッパーが PHP に追加できるので、 特にラッパーでできることの限界はありません。 現在登録されているラッパーの種類を知るには、 stream_get_wrappers() を使います。

リソースは次のような形でストリームとして参照されます: scheme://target

  • scheme(string) - 使用されるラッパの名称です。例として、 file, http, https, ftp, ftps, compress.zlib, compress.bz2, php などが含まれます。 PHP 組み込みのラッパについては、付録M を参照ください。もしラッパが指定されていない場合は、使用している関数の デフォルトが利用されます(通常は file://)。

  • target - 使用するラッパによって解釈が異なります。 ファイルシステムに関連したストリームの場合、 一般的にこのパラメータは対象となるファイルの ファイル名とパスを表します。 ネットワークに関連したストリームの場合、一般的に このパラメータはホスト名と、(多くの場合付加されるはずの) パス名です。 PHP 組み込みのラッパに、どのようにターゲットが解釈されるかは、 付録M を参照ください。

ストリームフィルタ

フィルタ は、ストリームから読み込まれたり、 あるいは、ストリームから書き込まれたするデータに対して何らかの 操作を行う、最終段階にあるコードです。 PHP スクリプトの内部で、 stream_filter_register() を使って、 あるいは拡張モジュールの内部で 第44章 に示された 関連する API を使って、カスタムフィルタを作成することができます。 現在登録されているフィルタの一覧を取得するには、 stream_get_filters() をお使いください。

ストリームコンテキスト

コンテキスト は、ストリームの挙動を変えたり、 拡張したりすることのできる パラメータ と ラッパ固有の オプション の集合です。 コンテキスト は、 stream_context_create() を使って生成しますが、 これは、ほとんどのファイルシステム関連のストリーム生成関数に 渡すことができます。(例えば fopen(), file(), file_get_contents() など)

オプション は、 stream_context_create() の呼び出し時に指定しますが、 後で stream_context_set_option() を使って 指定することもできます。 ラッパ固有の オプション については、 組み込みラッパの一覧に説明があります。 (付録M を参照ください)

さらに、stream_context_set_params() を使うことで、 パラメータ を、コンテキスト に対し指定することができます。なお、現在のところ、PHP にサポートされているコンテキストパラメータ は、 notification のみです。このパラメータの値は、 ストリームに発生した何らかのイベントを通知するために呼び出される関数の 名前でなくてはなりません。 通知関数は次のような 6 個のパラメータを取ります:

void my_notifier ( int notification_code, int severity, string message, int message_code, int bytes_transferred, int bytes_max )

notification_codeseverity は、下記の STREAM_NOTIFY_* 定数に該当する数値です。 もし、通知内容についての詳細メッセージがある場合、 messagemessage_code に適切な値が入ります。なお、これらの値の意味するところは使われている ラッパによって異なります。 bytes_transferredbytes_max には、場合に応じて値が埋められます。

インストール手順

ストリームは、バージョン 4.3.0 より、PHP の一部として 統合されています。有効にするために特別な手順を踏む必要はありません。

ストリームのクラス

ユーザ定義のラッパは、stream_wrapper_register() で、同関数の説明ページに記載されたクラス定義を使うことで、 登録することができます。

ユーザ定義のフィルタ用に、class php_user_filter が、 ベースとなる抽象クラスとしてあらかじめ定義されています。 ユーザ定義のフィルタの実装に関する詳細は、 stream_filter_register() を参照ください。

定義済み定数

以下の定数が定義されています。 この関数の拡張モジュールが PHP 組み込みでコンパイルされているか、 実行時に動的にロードされている場合のみ使用可能です。

定数説明
STREAM_FILTER_READ * stream_filter_append() または stream_filter_prepend() と共に使われます。 指定されたフィルタが 読み込みのときのみ 適用されることを示します。
STREAM_FILTER_WRITE * stream_filter_append() または stream_filter_prepend() と共に使われます。 指定されたフィルタが 書き込みのときのみ 適用されることを示します。
STREAM_FILTER_ALL * この定数は右の値と等価です: STREAM_FILTER_READ | STREAM_FILTER_WRITE
PSFS_PASS_ON *返値: ユーザ空間のフィルタが バケットを $out に返したことを 示します。
PSFS_FEED_ME *返値: ユーザ空間のフィルタが $out にバケットを返さなかったことを 示します。(つまり、変換されたデータを返す用意ができていないという ことです。)
PSFS_ERR_FATAL *返値: ユーザ空間のフィルタにおいて、 復旧不可能なエラーが発生したことを示します。 (つまり、不正なデータを受け取ったということです。)
STREAM_USE_PATHフラグ: stream が include_path を使ったかどうかを示します。
STREAM_REPORT_ERRORSフラグ: ストリームを開く際に、 ユーザ空間にある wrapper の側で、 trigger_error() を使ってエラーを発生させるかどうかを 示します。もし、このフラグがセットされていない場合は、 ユーザの側でエラーを投げてはいけません。
STREAM_CLIENT_ASYNC_CONNECT *非同期的にソケットを開きます。このオプションは、 STREAM_CLIENT_CONNECT フラグとともに使用する 必要があります。 stream_socket_client() と共に使われます。
STREAM_CLIENT_CONNECT *クライアントソケット接続を開きます。クライアントソケットは 常にこのフラグを含んでいる必要があります。 stream_socket_client() と共に使われます。
STREAM_CLIENT_PERSISTENT *stream_socket_client()を使って 開かれたソケットが、セッションをまたいでも保持されるよう 指示します。
STREAM_SERVER_BIND *stream_socket_server() で開かれたソケットが 特定のターゲットに関連付けられることを示します。 サーバーソケットには常にこのフラグが与えられているはずです。
STREAM_SERVER_LISTEN *stream_socket_server() で開かれ、 STREAM_SERVER_BIND によってターゲットに 関連付けられたストリームに、ソケットに対して接続待ちを開始するよう 指示します。 接続指向の転送(TCP のような)はこのフラグを使用する必要があります。 それ以外の場合はサーバソケットが有効になりません。 このフラグを非接続指向の転送(UDP のような)に使用するとエラーになります。
STREAM_NOTIFY_RESOLVE * 該当するストリームにおいて、リクエストされたリモートのドメイン名の 解決に成功したか、失敗したことを示します。 このとき、何が起こっているかについては、 severity を参照ください。
STREAM_NOTIFY_CONNECT 外部のリソースへの接続が確立されたことを示します。
STREAM_NOTIFY_AUTH_REQUIRED 指定されたリソースにアクセスするためには、さらに認証情報が必要です。 通常に、STREAM_NOTIFY_SEVERITY_ERRseverity (深刻度) と共に通知されます。
STREAM_NOTIFY_MIME_TYPE_IS リソースの mime タイプ が確認されました。 どのタイプと判定されたかについては、message を見てください。
STREAM_NOTIFY_FILE_SIZE_IS 確認されたリソースのサイズを表します。
STREAM_NOTIFY_REDIRECTED 外部リソースへのアクセスは、別の場所にリダイレクトされました。 詳細を知るには、message を調べてみてください。
STREAM_NOTIFY_PROGRESS ストリームにおける転送の進捗が、 bytes_transferred または、場合によっては bytes_max に現れていることを示します。
STREAM_NOTIFY_COMPLETED これ以上ストリームにデータがないことを示します。
STREAM_NOTIFY_FAILURE ストリームにおいて一般的なエラーが発生したことを示します。 エラーの詳細については、 messagemessage_code を調べてみてください。
STREAM_NOTIFY_AUTH_RESULT 認証が完了した(成功または失敗した)ことを示します。
STREAM_NOTIFY_SEVERITY_INFO 正常な状態における、エラーでない通知があることを示します。
STREAM_NOTIFY_SEVERITY_WARN 致命的でないエラーが発生したことを示します。処理は継続されます。
STREAM_NOTIFY_SEVERITY_ERR 致命的なエラーが発生したことを示します。処理は中断されます。
STREAM_IPPROTO_ICMP + ICMP ソケットを提供します。
STREAM_IPPROTO_IP + IP ソケットを提供します。
STREAM_IPPROTO_RAW + RAW ソケットを提供します。
STREAM_IPPROTO_TCP + TCP ソケットを提供します。
STREAM_IPPROTO_UDP + UDP ソケットを提供します。
STREAM_PF_INET + Internet Protocol バージョン 4(IPv4)です。
STREAM_PF_INET6 + Internet Protocol バージョン 6(IPv6)です。
STREAM_PF_UNIX + Unix システムの内部プロトコルです。
STREAM_SOCK_DGRAM + データグラムを提供します。これはコネクションレスのメッセージ (例: UDP)です。
STREAM_SOCK_RAW + raw ソケットを提供します。これは内部のネットワークプロトコルや インターフェースへのアクセス機能を提供します。通常、この形式の ソケットは root ユーザが使用します。
STREAM_SOCK_RDM + RDM(Reliably-delivered messages)ソケットを提供します。
STREAM_SOCK_SEQPACKET + シーケンシャルパケットストリームソケットを提供します。
STREAM_SOCK_STREAM + 帯域外データを転送するための、シーケンシャルで双方向の バイトストリーム(例: TCP)を提供します。

注意: * がつけられている定数は PHP 5.0.0 以降で使用可能です。

注意: + がつけられている定数は PHP 5.1.0 以降で使用可能で、 stream_socket_pair() とともに使用することが想定されています。 これらの定数の中にはあなたのシステムでは使用できないものがあるかもしれない ことに注意してください。

ストリームのエラー

ファイルやソケット関連の関数で処理に失敗するのと同じように、 ストリームにおける操作も様々な予測できる理由で失敗することがあります。 (例: リモートホストに接続できない、ファイルが見つからない、等) また、ストリーム関連の関数呼び出しは、 スクリプトの実行されるシステムにおいて、 利用しようとしているストリームが登録されていないことから失敗することも あります。どのタイプのストリームがインストールされた PHP でサポートされているかは、 stream_get_wrappers() の返す配列の内容を参照 してください。なお、他の PHP の内部関数と同様、 E_WARNING メッセージがエラー時に出力され、 エラーの原因を報告します。

例 1. file_get_contents() を使って さまざまな場所からデータを取得する

<?php
/* /home/bar にあるローカルファイルを読み出す */
$localfile = file_get_contents("/home/bar/foo.txt");

/* 上と同一だが、明示的に FILE スキームを指定している */
$localfile = file_get_contents("file:///home/bar/foo.txt");

/* HTTP を利用し、www.example.com にあるリモートのファイルを読み出す */
$httpfile  = file_get_contents("http://www.example.com/foo.txt");

/* HTTPS を利用し、www.example.com にあるリモートのファイルを読み出す */
$httpsfile = file_get_contents("https://www.example.com/foo.txt");

/* FTP を利用し、ftp.example.com にあるリモートのファイルを読み出す */
$ftpfile   = file_get_contents("ftp://user:pass@ftp.example.com/foo.txt");

/* FTPS を利用し、ftp.example.com にあるリモートのファイルを読み出す */
$ftpsfile  = file_get_contents("ftps://user:pass@ftp.example.com/foo.txt");
?>

例 2. https のサーバに対して POST リクエストを行う

<?php
/* https://secure.example.com/form_action.php に対して POST リクエストを送信
* ダミー値を持つ "foo" と "bar" というフォーム要素が含まれます。
*/

$sock = fsockopen("ssl://secure.example.com", 443, $errno, $errstr, 30);
if (!
$sock) die("$errstr ($errno)\n");

$data = "foo=" . urlencode("Fooの値") . "&bar=" . urlencode("Barの値");

fwrite($sock, "POST /form_action.php HTTP/1.0\r\n");
fwrite($sock, "Host: secure.example.com\r\n");
fwrite($sock, "Content-type: application/x-www-form-urlencoded\r\n");
fwrite($sock, "Content-length: " . strlen($data) . "\r\n");
fwrite($sock, "Accept: */*\r\n");
fwrite($sock, "\r\n");
fwrite($sock, "$data\r\n");
fwrite($sock, "\r\n");

$headers = "";
while (
$str = trim(fgets($sock, 4096)))
  
$headers .= "$str\n";

echo
"\n";

$body = "";
while (!
feof($sock))
  
$body .= fgets($sock, 4096);

fclose($sock);
?>

例 3. データを圧縮ファイルに書き込む

<?php
/* 任意の文字列を含む圧縮ファイルを作成
* ファイルは、compress.zlib ストリームを使っても、または単に
* コマンドラインで 'gzip -d foo-bar.txt.gz' を使っても読み出せます。
*/
$fp = fopen("compress.zlib://foo-bar.txt.gz", "wb");
if (!
$fp) die("ファイルが作成できませぬ.");

fwrite($fp, "これはテストです.\n");

fclose($fp);
?>

目次
stream_bucket_append --  bucket を brigade に追加する
stream_bucket_make_writeable --  操作する brigade から bucket オブジェクトを返す
stream_bucket_new --  現在のストリームで使用する新しい bucket を作成する
stream_bucket_prepend --  bucket を brigade に追加する
stream_context_create -- ストリームコンテキストを作成する
stream_context_get_default -- デフォルトのストリームコンテキストを取得する
stream_context_get_options -- ストリーム / ラッパ / コンテキストに設定されているオプションを取得する
stream_context_set_option -- ストリーム / ラッパ / コンテキストのオプションを設定する
stream_context_set_params -- ストリーム / ラッパ / コンテキストのパラメータを設定する
stream_copy_to_stream -- データをあるストリームから別のストリームにコピーする
stream_filter_append -- ストリームにフィルタを付加する
stream_filter_prepend -- フィルタをストリームに付加する
stream_filter_register -- php_user_filter に由来するクラスとして実装されたストリームフィルタを登録する
stream_filter_remove -- ストリームからフィルタを取り除く
stream_get_contents -- 残りのストリームを文字列に読み込む
stream_get_filters -- 登録されているフィルタのリストを取得する
stream_get_line -- 指定されたデリミタの位置までのデータを一行分としてストリームから読み込む
stream_get_meta_data -- ヘッダーあるいはメタデータをストリームまたはファイルポインタから取得する
stream_get_transports -- 登録されたソケットのトランスポートの一覧を取得する
stream_get_wrappers -- 登録されているストリームのラッパのリストを取得する
stream_register_wrapper -- stream_wrapper_register() へのエイリアス
stream_select -- select() システムコールと同等の操作を、 ストリームの配列に対して tv_sec と tv_usec で指定されたタイムアウト時間をもって行う
stream_set_blocking -- ストリームのブロックモードを有効にする / 解除する
stream_set_timeout -- ストリームにタイムアウトを設定する
stream_set_write_buffer -- 指定されたストリームのファイルバッファリングを有効にする
stream_socket_accept --  stream_socket_server() で作られたソケットの接続を受け入れる
stream_socket_client --  インターネットドメインまたは Unix ドメインのソケット接続を開く
stream_socket_enable_crypto --  接続済みのソケットについて暗号化の on/off を切り替える
stream_socket_get_name -- ローカルまたはリモートのソケットの名前を取得する
stream_socket_pair --  接続された、区別できないソケットストリームの組を作成する
stream_socket_recvfrom -- 接続されているかどうかにかかわらず、ソケットからのデータを受信する
stream_socket_sendto -- 接続されているかどうかにかかわらず、ソケットにデータを送信する
stream_socket_server --  インターネットドメインまたは Unix ドメインのサーバソケットを作成する
stream_wrapper_register -- PHP のクラスとして実装された URL ラッパを登録する
stream_wrapper_restore -- 事前に登録を解除された組み込みラッパを復元する
stream_wrapper_unregister -- URL ラッパの登録を解除する