封裝 PHP 串流上下文 (stream_context_create) 實作簡易 HTTP Client,支援 GET/POST、自訂 Header、Cookie、Referer、User-Agent、請求/回應 Header 記錄,無需 cURL 擴展即可運作。
<?php
class HttpClient {
public $buffer = ''; // 回應內容
public $referer = ''; // Referer 標頭
public $response = ''; // 回應 Header
public $request = ''; // 請求 Header
private $options = []; // 建構選項
public static function init(?HttpClient &$instance, array $options = []): HttpClient {
return $instance = new self($options);
}
private function __construct(array $options = []) {
$this->options = $options;
if (!empty($this->options['debug'])) {
ob_end_clean();
set_time_limit(0);
header('Content-Type: text/plain; charset=utf-8');
}
}
/** 發送 GET 請求 */
public function get(string $url, ?string $query = null, ?string $cookie = null): ?string {
$parsed = parse_url($url);
$host = $parsed['host'] ?? '';
// 組合查詢字串
if ($query) {
$url .= (strpos($url, '?') === false ? '?' : '&') . $query;
}
$header = $this->build_header($host, $cookie);
$context = $this->create_context('GET', $header);
$this->request = $header;
$this->response = implode("\r\n", get_headers($url) ?: []);
$this->buffer = @file_get_contents($url, false, $context);
return $this->buffer;
}
/** 發送 POST 請求 */
public function post(string $url, ?string $data = null, ?string $cookie = null): ?string {
$parsed = parse_url($url);
$host = $parsed['host'] ?? '';
$header = $this->build_header($host, $cookie);
if ($data) {
$header .= "Content-Length: " . strlen($data) . "\r\n";
}
$context = $this->create_context('POST', $header, $data);
$this->request = $header;
$this->response = implode("\r\n", get_headers($url) ?: []);
$this->buffer = @file_get_contents($url, false, $context);
return $this->buffer;
}
private function build_header(string $host, ?string $cookie): string {
$ua = $this->options['user_agent'] ?? ($_SERVER['HTTP_USER_AGENT'] ?? 'PHP-HttpClient/1.0');
$h = "Host: $host\r\n";
$h .= "Connection: close\r\n";
$h .= "Accept: */*\r\n";
$h .= "User-Agent: $ua\r\n";
$h .= "DNT: 1\r\n";
if ($cookie) $h .= "Cookie: $cookie\r\n";
if ($this->referer) $h .= "Referer: {$this->referer}\r\n";
return $h;
}
private function create_context(string $method, string $header, ?string $content = null): resource {
$opts = [
'http' => [
'method' => $method,
'header' => $header,
'ignore_errors' => true, // 取得非 2xx 回應內容
]
];
if ($content) $opts['http']['content'] = $content;
return stream_context_create($opts);
}
}
<?php
require 'HttpClient.class.php';
// 初始化(可設定 debug、user_agent)
HttpClient::init($client, [
'debug' => true,
'user_agent' => 'Mozilla/5.0 (compatible; MyBot/1.0)',
]);
// GET 請求
$client->get('https://httpbin.org/get', 'name=test&page=1');
echo "=== Request Header ===\n{$client->request}\n";
echo "=== Response Header ===\n{$client->response}\n";
echo "=== Body ===\n{$client->buffer}\n";
// POST 請求
$client->post('https://httpbin.org/post', 'field1=value1&field2=value2', 'session=abc123');
echo $client->buffer;
// 設定 Referer 後續請求
$client->referer = 'https://example.com/from-page';
$client->get('https://httpbin.org/headers');
| 功能 | HttpClient (stream) | cURL |
|---|---|---|
| GET/POST | ✓ | ✓ |
| 自訂 Header | ✓ | ✓ |
| Cookie 管理 | 手動 | 自動 (CookieJar) |
| 檔案上傳 | 困難 | ✓ (CURLFile) |
| HTTPS/SSL 驗證 | 依賴 php.ini | 細緻控制 |
| 代理伺服器 | stream context | ✓ |
| 非同步/多工 | ✗ | ✓ (curl_multi) |
| 效能 | 中等 | 高 |
put(), delete(), patch() 方法ClientInterface 相容框架