在PHP 中, stream_get_meta_data()是一個非常有用的函數,它用於獲取與流(stream)相關的各種元信息。很多開發者在使用該函數時,會好奇:
本文將對這個問題進行解析,並結合使用示例說明stream_get_meta_data()的實際功能和限制。
簡短回答是:不能直接識別協議類型。
雖然stream_get_meta_data()返回了很多有用的信息,如是否到達文件末尾( eof )、是否阻塞( blocked )、是否可讀/可寫等,但它不會直接返回流的協議類型。協議類型的信息實際上在創建流時已隱含在流資源中,但並不通過該函數暴露。
舉個例子:
<span><span><span class="hljs-variable">$fp</span></span><span> = </span><span><span class="hljs-title function_ invoke__">fopen</span></span><span>(</span><span><span class="hljs-string">"http://example.com"</span></span><span>, </span><span><span class="hljs-string">"r"</span></span><span>);
</span><span><span class="hljs-variable">$meta</span></span><span> = </span><span><span class="hljs-title function_ invoke__">stream_get_meta_data</span></span><span>(</span><span><span class="hljs-variable">$fp</span></span><span>);
</span><span><span class="hljs-title function_ invoke__">print_r</span></span><span>(</span><span><span class="hljs-variable">$meta</span></span><span>);
</span><span><span class="hljs-title function_ invoke__">fclose</span></span><span>(</span><span><span class="hljs-variable">$fp</span></span><span>);
</span></span>
返回的$meta數據結構大致如下:
<span><span><span class="hljs-title function_ invoke__">Array</span></span><span>
(
[wrapper_type] => http
[stream_type] => tcp_socket
[mode] => r
[unread_bytes] => </span><span><span class="hljs-number">0</span></span><span>
[seekable] =>
[uri] => </span><span><span class="hljs-attr">http</span></span><span>://example.com
[timed_out] =>
[blocked] => </span><span><span class="hljs-number">1</span></span><span>
[eof] =>
)
</span></span>
其中的wrapper_type就是最接近“協議類型”的一個字段,比如http 、 ftp 、 php等。雖然這並不是專門用於協議識別的字段,但我們可以間接通過它來判斷流使用了哪種協議。
wrapper_type : 這個字段表示流的封裝類型,也就是PHP 使用的“包裝器”,常常與協議相關。常見的值包括http 、 ftp 、 php 、 plainfile等。
stream_type : 更低層次的表示,比如tcp_socket 、 ssl 、 STDIO等,反映了實際傳輸方式。
如果你希望識別“協議”這個層面的信息,建議優先查看wrapper_type字段。
你可以封裝一個輔助函數,用來提取並返回協議信息。例如:
<span><span><span class="hljs-function"><span class="hljs-keyword">function</span></span></span><span> </span><span><span class="hljs-title">getStreamProtocol</span></span><span>(</span><span><span class="hljs-params"><span class="hljs-variable">$stream</span></span></span><span>) {
</span><span><span class="hljs-variable">$meta</span></span><span> = </span><span><span class="hljs-title function_ invoke__">stream_get_meta_data</span></span><span>(</span><span><span class="hljs-variable">$stream</span></span><span>);
</span><span><span class="hljs-keyword">return</span></span><span> </span><span><span class="hljs-variable">$meta</span></span><span>[</span><span><span class="hljs-string">'wrapper_type'</span></span><span>] ?? </span><span><span class="hljs-literal">null</span></span><span>;
}
</span></span>
使用示例:
<span><span><span class="hljs-variable">$stream</span></span><span> = </span><span><span class="hljs-title function_ invoke__">fopen</span></span><span>(</span><span><span class="hljs-string">'php://input'</span></span><span>, </span><span><span class="hljs-string">'r'</span></span><span>);
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-title function_ invoke__">getStreamProtocol</span></span><span>(</span><span><span class="hljs-variable">$stream</span></span><span>); </span><span><span class="hljs-comment">// 輸出: php</span></span><span>
</span><span><span class="hljs-title function_ invoke__">fclose</span></span><span>(</span><span><span class="hljs-variable">$stream</span></span><span>);
</span></span>
通過這個方式,你就可以基本判斷流的協議來源。
雖然stream_get_meta_data()並不會顯式地返回協議名稱,但它返回的wrapper_type字段足以幫助開發者判斷使用的協議或包裝器類型。這種間接識別方式在實際開發中已經非常實用。
小提示:在處理多種類型流資源時,務必注意兼容性和異常處理,尤其是涉及網絡或遠程流時。