PHP Streams (流) 為檔案、網路、壓縮、進程間通訊等提供統一的線性讀寫介面。本文系統解析 Stream 架構:scheme://target 結構、內建包裝器 (file, http, php, zip, data...)、傳輸層 (tcp, ssl, unix)、過濾器鏈、上下文選項、php:// 特殊流、自定義包裝器開發步驟,並展示實戰應用場景。
scheme://target ├── scheme (包裝器名稱) → 決定如何解析 target、提供什麼操作 └── target (路徑/參數) → 包裝器特定語法 例子: file:///var/log/app.log → 本地檔案 https://api.example.com/users → HTTP 請求 php://input → POST 原始資料流 compress.zlib://data.gz → 解壓縮流 zip://archive.zip#file.txt → ZIP 內部檔案
php:// 特殊流家族
| 流 | 用途 | 模式 |
|---|---|---|
php://stdin | 標準輸入 | 唯讀 |
php://stdout | 標準輸出 | 唯寫 |
php://stderr | 標準錯誤 | 唯寫 |
php://input | POST 原始請求體 | 唯讀 (僅非 multipart/form-data) |
php://output | 輸出緩衝區 | 唯寫 |
php://memory | 記憶體暫存 (資料常駐記憶體) | 讀寫 |
php://temp | 臨時檔案 (超過限制自動落盤) | 讀寫 |
php://filter/... | 元包裝器:套用過濾器 | 讀/寫 |
Stream Context (上下文) 自定義 HTTP 請求
[ 'method' => 'POST', 'header' => "Authorization: Bearer $token\r\n" . "Content-Type: application/json\r\n", 'content' => json_encode(['action'=>'sync', 'data'=>[1,2,3]]), 'timeout' => 30, 'ignore_errors' => true, // 取得 4xx/5xx 回應內容 ] ]; $ctx = stream_context_create($opts); // 使用 context 發送請求 $response = file_get_contents('https://api.example.com/sync', false, $ctx); $status = $http_response_header[0] ?? 'HTTP/1.1 000'; // 解析狀態碼自定義包裝器開發步驟 (實現 Amazon S3、Google Cloud Storage 等)
- 建立類別實現
streamWrapper介面方法:stream_open,stream_read,stream_write,stream_stat,stream_close,url_stat,dir_opendir...- 註冊:
stream_wrapper_register('s3', 'MyS3Wrapper')。- 使用:
fopen('s3://bucket/key', 'r')、file_get_contents('s3://bucket/key')、mkdir('s3://bucket/dir')等標準檔案函數無縫運作。bucket = $parsed['host']; $this->key = ltrim($parsed['path'], '/'); $this->client = new Aws\S3\S3Client([...]); // AWS SDK $this->position = 0; return true; } public function stream_read($count) { $result = $this->client->getObject([ 'Bucket' => $this->bucket, 'Key' => $this->key, 'Range' => "bytes={$this->position}-" . ($this->position + $count - 1) ]); $data = $result['Body']->getContents(); $this->position += strlen($data); return $data; } public function stream_write($data) { /* S3 不支援隨機寫入,可拋出異常 */ return 0; } public function stream_tell() { return $this->position; } public function stream_eof() { return $this->position >= $this->getSize(); } public function stream_stat() { return ['size'=>$this->getSize(), 'mode'=>0644, 'mtime'=>time()]; } public function url_stat($path, $flags) { /* 靜態資訊 */ return $this->stream_stat(); } public function stream_close() { $this->client = null; } private function getSize() { /* HEAD Object 取得大小 */ return 1024; } } stream_wrapper_register('s3', 'MyS3Wrapper') or die("註冊失敗"); // 現在可像本地檔案一樣操作 S3 $fp = fopen('s3://my-bucket/large-video.mp4', 'r'); fseek($fp, 1000000); // 隨機跳轉 echo fread($fp, 1024); fclose($fp);實戰應用場景總覽
| 場景 | Stream 方案 | 優勢 |
|---|---|---|
| 大檔案上傳/下載 | php://temp + 分塊讀寫 | 記憶體安全、支援斷點續傳 |
| API 請求無需 cURL | file_get_contents + HTTP Context | 零依賴、程式碼簡潔 |
| 資料管線處理 | php://filter 級聯過濾 | 串流處理、無需落地中間檔 |
| 雲存儲抽象化 | 自定義 s3://, gcs:// 包裝器 | 業務代碼無感遷移、單元測試易 Mock |
| 壓縮/解壓縮 | compress.zlib://, zip:// | 透明壓縮、標準函數操作 |
| 進程間通訊 | unix://, tcp:// sockets | 統一介面、支援非阻塞 |
Streams 是 PHP 「萬物皆流」的基礎設施。掌握包裝器、上下文、過濾器三大核心,能以極低成本解決跨協議資料存取、串流處理、雲資源抽象化等架構級難題。