今日は、PHP ストリームとラッパーの概念と使用法について説明します。皆さんのためにまとめておきます。
ストリームの概念が php4.3 で導入されたことはわかっています。これはストリーミング データの抽象化であり、ファイル データ、ネットワーク データ、圧縮データなどのデータ操作を統合するために使用されます。ファイルシステム関数は共有できます。たとえば、file_get_contents() 関数はローカル ファイルを開いて URL にアクセスできます。簡単に言うと、ストリームはストリーミング データの動作を示すリソース オブジェクトです。
直線的な方法で読み取りと書き込みを行い、ストリーム内のどこでも検索できます。
ストリームはデータベース抽象化層に似ており、どのような種類のデータベースが使用されても、データは抽象化層の上で同じように操作されます。ローカルファイルであっても、リモートファイルであっても、ストリーミングデータであれば操作方法は同じです。
ストリームの概念からラッパーの概念が導出されます。ストリームは統一された操作の観点から生成される概念ですが、ラッパーはストリームデータの内容を理解することから始まり、つまり、この統一された操作方法でさまざまなコンテンツを操作または設定する方法です。
これらのコンテンツはすべてストリームで表示されますが、コンテンツのルールは異なります。たとえば、http プロトコルで送信されるデータは、ストリーミング方法だけです。 http ラッパーは http プロトコルで送信されるデータの意味を理解します。ストリームは水を流すパイプですが、流れ出すのはデータであり、ラッパーはストリーム パイプの外層に配置されることがわかります。 . ストリーミング データの意味を理解し、それを操作できるインタープリタ。
公式マニュアルには、「ラッパーとは、特別なプロトコルまたはエンコーディングを処理する方法をストリームに指示する追加のコードです。」この文の意味がわかりますか?
ラッパーはネストできます。フローをラッパーでラップした後、外側のラッパーに対してフローの役割を果たします。
PHP の下部にあります。実装された C 言語開発ドキュメントには次の説明があります:
ストリーム API は 1 組の異なるレベルで動作します。基本レベルでは、API はストリーミング データ ソースを表す php_stream オブジェクトを定義します。少し高いレベルでは、API は以下を定義します。 php_stream_wrapper オブジェクト。
下位レベルの php_stream オブジェクトをラップして、URL のコンテンツとメタデータを取得し、コンテキスト パラメーターを追加し、ラッパーの動作を調整する機能を提供します。
ストリームを開いた後は、任意の数のフィルターを適用できます。上記のストリーミング データはフィルターによって処理されますが、フィルターという言葉は少し不正確で誤解を招きやすいと思います。
文字通りの意味は、データを削除したり、追加したり、変更したりできるため、データ調整器と呼ぶべきであるようですが、歴史的な理由により、フィルターとも呼ばれます。誰もがそれを理解している限り。
それらの違いを説明するために、次のような言葉がよく使われます:
リソースとデータ: リソースは比較的マクロな用語で、通常はデータを含みますが、データはより具体的な用語であり、プログラムを開発するときによく言われます。ソフトウェア計画におけるこれらは、ソフトウェア設計とプログラム開発の違いと同様に同義語です。
コンテキストとパラメータ: コンテキストは比較的マクロな用語であり、特に通信自体のパラメータであり、パラメータという用語は、上で説明した関数
など、より具体的なものでよく使用されます。 、具体的な内容を見てみましょう:
php でサポートされているプロトコルとラッパーについては、こちらを参照してください: http://php.net/manual/zh/wrappers.php:
(著者注: 原題は:サポートされているプロトコルとパッケージ化プロトコル。中国語の翻訳は少し誤解を招きますが、正確に言うと、サポートされているプロトコルとラッパーです。これは英語版から非常に明らかです)
一部のプロトコルとラッパーはデフォルトでサポートされており、stream_get_wrappers(また、ラッパーをカスタマイズして、stream_wrapper_register() で登録することもできます
RFC 3986 では区切り文字として: を使用できますが、PHP では :// のみが許可されるため、「scheme://target」の形式を使用してください。 URL
file:// — 访问本地文件系统,在用文件系统函数时默认就使用该包装器 http:// — 访问 HTTP(s) 网址 ftp:// — 访问 FTP(s) URLs php:// — 访问各个输入/输出流(I/O streams) zlib:// — 压缩流 data:// — 数据(RFC 2397) glob:// — 查找匹配的文件路径模式 phar:// — PHP 归档 ssh2:// — Secure Shell 2 rar:// — RAR ogg:// — 音频流 expect:// — 处理交互式的流
カスタム ラッパーを実装してみてはいかがでしょうか:
fopen、fwrite、fread、fgets、feof、rewind、file_put_contents、file_get_contents などのファイル システム関数を使用してストリームを操作する場合、データは最初に渡されます。定義したラッパークラスオブジェクトとラッパー 再度操作フローに戻ります。
カスタム ストリーム ラッパーを実装するにはどうすればよいですか? PHP はクラス プロトタイプを提供しますが、これはインターフェイスやクラスではなく単なるプロトタイプであり、継承には使用できません:
streamWrapper { /* 属性 */ public resource $context ; /* 方法 */ __construct ( void ) __destruct ( void ) public bool dir_closedir ( void ) public bool dir_opendir ( string $path , int $options ) public string dir_readdir ( void ) public bool dir_rewinddir ( void ) public bool mkdir ( string $path , int $mode , int $options ) public bool rename ( string $path_from , string $path_to ) public bool rmdir ( string $path , int $options ) public resource stream_cast ( int $cast_as ) public void stream_close ( void ) public bool stream_eof ( void ) public bool stream_flush ( void ) public bool stream_lock ( int $operation ) public bool stream_metadata ( string $path , int $option , mixed $value ) public bool stream_open ( string $path , string $mode , int $options , string &$opened_path ) public string stream_read ( int $count ) public bool stream_seek ( int $offset , int $whence = SEEK_SET ) public bool stream_set_option ( int $option , int $arg1 , int $arg2 ) public array stream_stat ( void ) public int stream_tell ( void ) public bool stream_truncate ( int $new_size ) public int stream_write ( string $data ) public bool unlink ( string $path ) public array url_stat ( string $path , int $flags ) }
在这个原型里面定义的方法,根据自己需要去定义,并不要求全部实现,这就是为什么不定义成接口的原因,因为有些实现根本用不着某些方法,
这带来很多灵活性,比如包装器是不支持删除目录rmdir功能的,那么就不需要实现streamWrapper::rmdir
由于未实现它,如果用户在包装器上调用rmdir将有错误抛出,要自定义这个错误那么也可以实现它并在其内部抛出错误
streamWrapper也不是一个预定义类,测试class_exists("streamWrapper")就知道,它只是一个指导开发者的原型
官方手册提供了一个例子:http://php.net/manual/zh/stream.streamwrapper.example-1.php
本博客提供一个从drupal8系统中抽取修改过的包装器例子,请看drupal8源码分析关于流那一部分
流系列函数,官方手册:http://php.net/manual/zh/ref.stream.php
常用的函数如下:
stream_bucket_append函数:为队列添加数据 stream_bucket_make_writeable函数:从操作的队列中返回一个数据对象 stream_bucket_new函数:为当前队列创建一个新的数据 stream_bucket_prepend函数:预备数据到队列 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类执行 stream_filter_remove函数:从一个数据流中移除过滤器 stream_get_contents函数:读取数据流中的剩余数据到字符串 stream_get_filters函数:返回已经注册的数据流过滤器列表 stream_get_line函数:按照给定的定界符从数据流资源中获取行 stream_get_meta_data函数:从封装协议文件指针中获取报头/元数据 stream_get_transports函数:返回注册的Socket传输列表 stream_get_wrappers函数:返回注册的数据流列表 stream_register_wrapper函数:注册一个用PHP类实现的URL封装协议 stream_select函数:接收数据流数组并等待它们状态的改变 stream_set_blocking函数:将一个数据流设置为堵塞或者非堵塞状态 stream_set_timeout函数:对数据流进行超时设置 stream_set_write_buffer函数:为数据流设置缓冲区 stream_socket_accept函数:接受由函数stream_ socket_server()创建的Socket连接 stream_socket_client函数:打开网络或者UNIX主机的Socket连接 stream_socket_enable_crypto函数:为一个已经连接的Socket打开或者关闭数据加密 stream_socket_get_name函数:获取本地或者网络Socket的名称 stream_socket_pair函数:创建两个无区别的Socket数据流连接 stream_socket_recvfrom函数:从Socket获取数据,不管其连接与否 stream_socket_sendto函数:向Socket发送数据,不管其连接与否 stream_socket_server函数:创建一个网络或者UNIX Socket服务端 stream_wrapper_restore函数:恢复一个事先注销的数据包 stream_wrapper_unregister函数:注销一个URL地址包
相信看了这些案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
相关阅读:
以上がPHPのStreamsとラッパーラッパーの使い方の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。