首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

深入理解 PHP Stream 流:概念、Socket 應用、上下文、過濾器與自訂封裝協議

     編輯:PHP 相關知識

深入理解 PHP Stream 流:概念、Socket 應用、上下文、過濾器與自訂封裝協議

Stream(流)是 PHP 處理 I/O 的核心抽象,源自 UNIX 管道概念。本文從基本概念切入,示範 Socket 通訊、HTTP 上下文、內建與自訂過濾器,並簡述 Stream Wrapper 封裝協議。

1. Stream 基本概念

  • **流向**:輸入流(讀取)、輸出流(寫入)。
  • **封裝協議**:file://、https://、ftp://、php://、data://、zlib:// 等。
  • **上下文**:stream_context_create() 設定協定選項(HTTP Header、SSL 驗證、FTP 登入等)。
  • **過濾器**:掛載於讀寫流程中轉換資料(編碼、壓縮、加密、日誌)。

2. Socket 通訊範例

<?php
$post = ['author'=>'Gonn', 'mail'=>'gonn@example.com', 'text'=>'Hello'];
$data = http_build_query($post);

$fp = stream_socket_client("tcp://example.com:80", $errno, $errstr, 5);
if (!$fp) die("連線失敗: $errstr");

$req  = "POST /api/comment HTTP/1.1\r\n";
$req .= "Host: example.com\r\n";
$req .= "Content-Type: application/x-www-form-urlencoded\r\n";
$req .= "Content-Length: " . strlen($data) . "\r\n";
$req .= "Connection: close\r\n\r\n";
$req .= $data . "\r\n";

fwrite($fp, $req);
while (!feof($fp)) {
  echo fgets($fp, 1024);
}
fclose($fp);
?>

等同於 fsockopen,但 stream_socket_client 支援更多協定(ssl://、udp://、unix://)。

3. HTTP 上下文發送 POST

<?php
$opts = [
  'http' => [
    'method'  => 'POST',
    'header'  => "Content-Type: application/x-www-form-urlencoded\r\nContent-Length: " . strlen($data),
    'content' => $data,
    'timeout' => 30
  ]
];
$context = stream_context_create($opts);
$result = file_get_contents('https://example.com/api/comment', false, $context);
?>

file_get_contents、fopen、copy 等函數均接受 $context 參數,統一介面操作不同協定。

4. 內建過濾器應用

<?php
$fp = fopen('test.txt', 'w+');
// 掛載 rot13 過濾器於寫入流
stream_filter_append($fp, 'string.rot13', STREAM_FILTER_WRITE);
fwrite($fp, "Hello World\n");
rewind($fp);
fpassthru($fp); // 輸出:Uryyb Jbeyq
fclose($fp);

// 列出所有內建過濾器
print_r(stream_get_filters());
/* 輸出範例
Array (
  [0] => convert.iconv.*
  [1] => string.rot13
  [2] => string.toupper
  [3] => string.tolower
  [4] => string.strip_tags
  [5] => zlib.*
  [6] => bzip2.*
  ...
)
*/

5. 自訂過濾器:MD5 雜湊 + 日誌回呼

<?php
class MD5_Filter extends php_user_filter {
  public function filter($in, $out, &$consumed, $closing) {
    while ($bucket = stream_bucket_make_writeable($in)) {
      $bucket->data = md5($bucket->data);
      $consumed += $bucket->datalen;
      stream_bucket_append($out, $bucket);
    }
    // 回呼日誌函數
    if (isset($this->params['log_callback']) && is_callable($this->params['log_callback'])) {
      call_user_func($this->params['log_callback'], $bucket->data);
    }
    return PSFS_PASS_ON;
  }
}
stream_filter_register('string.md5', 'MD5_Filter');

// 使用
$logCb = function($data) {
  file_put_contents('stream.log', date('Y-m-d H:i:s') . " MD5: $data\n", FILE_APPEND);
};
$fp = fopen('data.txt', 'w');
stream_filter_prepend($fp, 'string.md5', STREAM_FILTER_WRITE, ['log_callback' => $logCb]);
fwrite($fp, "敏感資料");
fclose($fp);

6. Stream Wrapper 封裝協議(簡述)

實作 stream_wrapper_register('myproto', 'MyProto_Handler'),即可讓 fopen('myproto://path')、file_get_contents('myproto://path') 使用自訂類別處理。適用於虛擬檔案系統、資料庫 Blob 存取、雲端儲介面統一等場景。

總結

  • Stream 統一了檔案、網路、壓縮、加密等 I/O 操作介面。
  • 善用 stream_context 簡化 HTTP/FTP/SSL 參數設定。
  • 過濾器模式適合橫切關注點(日誌、審計、轉碼)。
  • Wrapper 讓 PHP 能以檔案系統語義存取任意資料源。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved