Stream(流)是 PHP 4.3 引入的統一資源抽象層,將檔案、網路、壓縮、進程間通訊等「可讀寫、可定位」的資源統一為 scheme://target 形式,使用相同函數族(fopen/fread/fwrite/fseek 等)操作。
print_r(stream_get_wrappers()); /* Array ( [0] => https [1] => ftps [2] => compress.zlib [3] => compress.bzip2 [4] => php [5] => file [6] => glob [7] => data [8] => http [9] => ftp [10] => zip [11] => phar ) */
file:// 預設,本地檔案系統。https:///https://、ftp:// 網路協議。compress.zlib:///compress.bzip2:// 透明壓縮/解壓。php:// 內部 I/O:stdin/stdout/stderr/input/memory/temp/filter。data:// 內嵌資料(RFC 2397)。phar:// PHP 封存檔。curl -d "raw=data&foo=bar" https://localhost/input.php
// $_POST 只解析 application/x-www-form-urlencoded
echo file_get_contents('php://input'); // 取得完整原始字串
$fp = fopen('php://temp', 'r+'); // 超過 2MB 自動落地臨時檔
fwrite($fp, "大量資料...");
rewind($fp);
echo stream_get_contents($fp);
// 寫入時 ROT13 編碼
file_put_contents('php://filter/write=string.rot13/resource=file:///tmp/test.txt', 'Hello');
// 讀取時大寫 + ROT13
echo file_get_contents('php://filter/read=string.toupper|string.rot13/resource=https://example.com');
Context 允許在不改變包裝器代碼的情況下修改行為(如 HTTP Header、SSL 選項、FTP 被動模式)。
$opts = [
'http' => [
'method' => 'POST',
'header' => "Content-Type: application/x-www-form-urlencoded\r\n" .
"Authorization: Bearer TOKEN\r\n",
'content' => http_build_query(['foo' => 'bar']),
'timeout' => 10,
],
];
$ctx = stream_context_create($opts);
$resp = file_get_contents('https://api.example.com/endpoint', false, $ctx);
stream_context_set_default(['http' => ['timeout' => 5]]); // 全域生效
| 場景 | Stream 方案 |
|---|---|
| 大檔案分片上傳 | fopen('php://input') 邊讀邊寫磁碟,不佔記憶體 |
| 透明讀取 .gz 日誌 | fopen('compress.zlib:///var/log/app.log.gz') |
| 無臨時檔處理上傳 | php://temp 當緩衝區 |
| 動態生成壓縮包下載 | php://output + zip:// 串流輸出 |
| PaaS 無實體檔案系統 | 自定義 s3://、gcs:// 包裝器,代碼零修改遷雲 |
實作 stream_wrapper_register() 介面:
class S3Wrapper {
public $context;
public function stream_open($path, $mode, $options, &$opened_path) { /* 連接 S3 */ return true; }
public function stream_read($count) { /* 從 S3 讀取 */ return $data; }
public function stream_write($data) { /* 寫入 S3 */ return strlen($data); }
public function stream_tell() { return $this->position; }
public function stream_eof() { return $this->position >= $this->size; }
public function stream_seek($offset, $whence) { /* 定位 */ return true; }
public function stream_stat() { return ['size'=>$this->size]; }
public function url_stat($path, $flags) { return ['size'=>$this->size]; }
}
stream_wrapper_register('s3', 'S3Wrapper') or die('註冊失敗');
// 之後即可 fopen('s3://bucket/key', 'r')
php://temp 避免記憶體爆炸。fopen/fread/fwrite 風格。Streams 是 PHP 最被低估的強大抽象。掌握它,能以極低成本解決檔案、網路、壓縮、雲儲存的統一存取問題。