PHP 中为 cURL、Guzzle 和 file_get_contents 配置代理,就是通过设置 HTTP 客户端选项或流上下文(stream context),把外发请求经指定的代理服务器转发,通常需要指定代理的主机、端口和认证凭据。
在 PHP 中使用代理服务器,可以让应用隐藏源 IP 地址、绕过地域限制、访问内网资源,或在网页抓取和 API 调用中控制请求频率。具体选用哪种方式,取决于所需的控制粒度、请求的复杂度以及错误处理的要求。
使用 cURL
cURL 是功能强大的 HTTP 请求库,对连接参数(包括代理设置)提供了充分的控制能力。它是复杂网络交互的常用选择,通常以 PHP 扩展(php-curl)的形式提供。
基本代理配置
要让请求经 HTTP 或 HTTPS 代理转发,请使用 CURLOPT_PROXY 和 CURLOPT_PROXYPORT。
<?php
$ch = curl_init();
// 目标 URL
curl_setopt($ch, CURLOPT_URL, 'http://example.com/api/data');
// 代理设置
curl_setopt($ch, CURLOPT_PROXY, 'proxy.example.com');
curl_setopt($ch, CURLOPT_PROXYPORT, 8080);
// 以字符串形式返回传输结果,而不是直接输出
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
if (curl_errno($ch)) {
echo 'cURL error: ' . curl_error($ch);
} else {
echo $response;
}
curl_close($ch);
?>
SOCKS 代理
cURL 支持 SOCKS 代理(SOCKS4、SOCKS4a、SOCKS5、SOCKS5h)。用 CURLOPT_PROXYTYPE 指定代理类型。
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://example.com/api/data');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// SOCKS5 代理设置
curl_setopt($ch, CURLOPT_PROXY, 'socks5.example.com');
curl_setopt($ch, CURLOPT_PROXYPORT, 1080);
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); // 或 CURLPROXY_SOCKS4、CURLPROXY_SOCKS4A、CURLPROXY_SOCKS5_HOSTNAME
$response = curl_exec($ch);
if (curl_errno($ch)) {
echo 'cURL error: ' . curl_error($ch);
} else {
echo $response;
}
curl_close($ch);
?>
带认证的代理
对于需要认证的代理,使用 CURLOPT_PROXYUSERPWD,值为 username:password 形式的字符串。
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://example.com/api/data');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// 带认证的代理设置
curl_setopt($ch, CURLOPT_PROXY, 'authproxy.example.com');
curl_setopt($ch, CURLOPT_PROXYPORT, 8080);
curl_setopt($ch, CURLOPT_PROXYUSERPWD, 'proxyuser:proxypassword');
// 可选:指定代理认证方式(如 CURLAUTH_BASIC、CURLAUTH_DIGEST)
// curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
$response = curl_exec($ch);
if (curl_errno($ch)) {
echo 'cURL error: ' . curl_error($ch);
} else {
echo $response;
}
curl_close($ch);
?>
HTTPS 代理(CONNECT 隧道)
通过 HTTP 代理连接 HTTPS 目标时,cURL 会使用 HTTP CONNECT 方法建立隧道。CURLOPT_HTTPPROXYTUNNEL 可以显式启用该行为,不过通常会自动处理。
<?php
$ch = curl_init();
// 目标 HTTPS URL
curl_setopt($ch, CURLOPT_URL, 'https://secure.example.com/data');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// 代理设置
curl_setopt($ch, CURLOPT_PROXY, 'proxy.example.com');
curl_setopt($ch, CURLOPT_PROXYPORT, 8080);
// 为经 HTTP 代理访问 HTTPS 启用隧道(通常隐式启用)
curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, true);
// 处理 SSL 证书校验(测试时关闭,生产环境开启)
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$response = curl_exec($ch);
if (curl_errno($ch)) {
echo 'cURL error: ' . curl_error($ch);
} else {
echo $response;
}
curl_close($ch);
?>
代理相关的常用 cURL 选项
CURLOPT_TIMEOUT:cURL 操作的最长时间(秒)。CURLOPT_CONNECTTIMEOUT:建立连接的最长时间(秒)。CURLOPT_FOLLOWLOCATION:跟随 HTTP 响应中的Location:头。CURLOPT_MAXREDIRS:最多跟随的重定向次数。CURLOPT_SSL_VERIFYPEER、CURLOPT_SSL_VERIFYHOST:控制 SSL 证书校验。生产环境请设为true。CURLOPT_HEADER:在输出中包含响应头。
使用 Guzzle
Guzzle 是流行的 PHP HTTP 客户端,在 cURL 之上提供了更高层的抽象,简化了常见的 HTTP 任务。需通过 Composer 安装。
基本代理配置
Guzzle 的客户端和请求都接受 proxy 选项,可以在客户端层面全局设置,也可以按请求单独设置。
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;
$client = new Client([
// 该客户端所有请求的基础 URI
'base_uri' => 'http://example.com/',
// 客户端的全局代理设置
'proxy' => 'http://proxy.example.com:8080',
]);
try {
$response = $client->request('GET', 'api/data');
echo $response->getBody();
} catch (GuzzleHttp\Exception\RequestException $e) {
echo 'Guzzle error: ' . $e->getMessage();
}
?>
带认证的代理
对于 HTTP/HTTPS 代理,直接把认证凭据写进代理 URI 中。
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;
$client = new Client([
'base_uri' => 'http://example.com/',
// 带认证的代理
'proxy' => 'http://proxyuser:[email protected]:8080',
]);
try {
$response = $client->request('GET', 'api/data');
echo $response->getBody();
} catch (GuzzleHttp\Exception\RequestException $e) {
echo 'Guzzle error: ' . $e->getMessage();
}
?>
SOCKS 代理
在代理 URI 中使用 socks 协议前缀来指定 SOCKS 代理。
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;
$client = new Client([
'base_uri' => 'http://example.com/',
// SOCKS5 代理
'proxy' => 'socks5://socks5.example.com:1080',
]);
try {
$response = $client->request('GET', 'api/data');
echo $response->getBody();
} catch (GuzzleHttp\Exception\RequestException $e) {
echo 'Guzzle error: ' . $e->getMessage();
}
?>
按请求设置代理
proxy 选项可以针对单个请求覆盖或单独指定。
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;
$client = new Client(); // 无全局代理
try {
$response = $client->request('GET', 'http://example.com/api/data', [
'proxy' => 'http://perrequestproxy.example.com:8080', // 仅用于本次请求的代理
]);
echo $response->getBody();
} catch (GuzzleHttp\Exception\RequestException $e) {
echo 'Guzzle error: ' . $e->getMessage();
}
?>
代理相关的常用 Guzzle 选项
proxy:代理 URI 字符串(http://、https://、socks4://、socks5://)。verify:控制 SSL 证书校验(true、false或 CA 证书包路径)。timeout:请求的总超时时间(秒)。connect_timeout:连接服务器的超时时间(秒)。allow_redirects:控制重定向处理(true、false或选项数组)。
使用 file_get_contents
file_get_contents 是读取文件内容(包括 URL)的简单函数。它可以通过流上下文配置代理,但与 cURL 或 Guzzle 相比,控制能力和错误处理都更弱。它适合代理需求简单的基本 HTTP/HTTPS 请求。
基本代理配置
使用 stream_context_create 在 http 选项中定义代理设置。
<?php
$proxy = 'tcp://proxy.example.com:8080';
$url = 'http://example.com/api/data';
$context = stream_context_create([
'http' => [
'proxy' => $proxy,
'request_fulluri' => true, // 使用 HTTP 代理时必需
],
]);
$response = @file_get_contents($url, false, $context);
if ($response === false) {
echo 'Failed to retrieve content via proxy.';
} else {
echo $response;
}
?>
使用 HTTP 代理时,request_fulluri 必须设为 true,它会让客户端在请求行中发送完整 URI(例如 GET http://example.com/path HTTP/1.0)。
HTTPS 代理
对于 HTTPS 目标,https 流封装器处理代理的方式与 http 类似。
<?php
$proxy = 'tcp://proxy.example.com:8080';
$url = 'https://secure.example.com/data';
$context = stream_context_create([
'http' => [ // 注意:CONNECT 隧道的代理配置仍放在 'http' 下
'proxy' => $proxy,
'request_fulluri' => true,
],
'ssl' => [ // SSL/TLS 校验选项
'verify_peer' => false, // 测试时关闭,生产环境开启
'verify_peer_name' => false,
],
]);
$response = @file_get_contents($url, false, $context);
if ($response === false) {
echo 'Failed to retrieve content via proxy.';
} else {
echo $response;
}
?>
带认证的代理
file_get_contents 的代理认证通常通过在 http 上下文选项中手动设置 Proxy-Authorization 头来实现。
<?php
$proxy = 'tcp://proxy.example.com:8080';
$url = 'http://example.com/api/data';
$proxyUser = 'proxyuser';
$proxyPass = 'proxypassword';
// 将 username:password 做 Base64 编码,用于 Basic 认证
$authHeader = 'Proxy-Authorization: Basic ' . base64_encode("$proxyUser:$proxyPass");
$context = stream_context_create([
'http' => [
'proxy' => $proxy,
'request_fulluri' => true,
'header' => $authHeader,
],
]);
$response = @file_get_contents($url, false, $context);
if ($response === false) {
echo 'Failed to retrieve content via proxy.';
} else {
echo $response;
}
?>
file_get_contents 使用代理的局限
- 不支持 SOCKS 代理: PHP 的流封装器原生不支持 SOCKS 代理。
- 错误处理有限: 错误信息很少,只能依靠警告或
false返回值。 - 控制力弱: 对请求头、超时和重定向的精细控制不够灵活。
- 性能: 在并发或大量请求场景下,性能可能不如 cURL。
PHP 代理方案对比
| 特性 | cURL(通过 php-curl) |
Guzzle(通过 Composer) | file_get_contents(通过流上下文) |
|---|---|---|---|
| 易用性 | 中等(直接设置选项) | 高(面向对象、链式接口) | 高(函数调用简单,只需配置上下文) |
| 代理类型 | HTTP、HTTPS(CONNECT)、SOCKS4/4a/5/5h | HTTP、HTTPS(CONNECT)、SOCKS4/5 | HTTP、HTTPS(CONNECT) |
| 认证方式 | CURLOPT_PROXYUSERPWD |
写入 URI(user:pass@host) |
手动设置 Proxy-Authorization 头 |
| 错误处理 | 详细(curl_errno、curl_error) |
完善(异常、PSR-7 响应) | 基础(返回 false、警告) |
| 控制粒度 | 高(可精细控制全部 cURL 选项) | 高(封装 cURL,提供高层选项) | 低(仅限流上下文选项) |
| SSL 校验 | CURLOPT_SSL_VERIFYPEER、CURLOPT_SSL_VERIFYHOST |
verify 选项 |
ssl 上下文选项(verify_peer、verify_peer_name) |
| 重定向处理 | CURLOPT_FOLLOWLOCATION、CURLOPT_MAXREDIRS |
allow_redirects 选项 |
有限(HTTP 自动跟随,可配置项少) |
| 依赖 | PHP cURL 扩展 | PHP cURL 扩展、Composer、Guzzle 包 | 无(PHP 内置函数) |
| 最佳适用场景 | 复杂、高性能、底层集成 | 现代应用、REST API、完善的错误处理 | 基础 GET 请求的简单快速脚本 |
