Nếu bạn đang viết một trình phân tích, tự động hóa việc thu thập dữ liệu hoặc vượt qua các hạn chế về IP — không thể thiếu proxy trong PHP. Trong hướng dẫn này, chúng ta sẽ xem xét hai công cụ chính: cURL tích hợp sẵn và thư viện phổ biến Guzzle HTTP Client — với các ví dụ mã sẵn có mà bạn có thể sử dụng ngay trong dự án.
Tại sao cần proxy trong các dự án PHP
PHP vẫn là một trong những ngôn ngữ phổ biến nhất cho tự động hóa phía máy chủ, và các tác vụ yêu cầu proxy thường xuyên xảy ra. Dưới đây là những kịch bản chính mà không có proxy sẽ không thể thực hiện:
- Phân tích các trang web và thị trường — Wildberries, Ozon, Avito, AliExpress chặn IP sau vài chục yêu cầu. Proxy cho phép phân phối tải giữa các địa chỉ khác nhau và không bị nhận 403/429.
- Thu thập dữ liệu từ các nguồn phụ thuộc vào địa lý — giá cả, kết quả tìm kiếm, nội dung có thể khác nhau tùy theo quốc gia. Proxy với vị trí địa lý cần thiết giải quyết vấn đề này.
- Vượt qua giới hạn tần suất — nhiều API giới hạn số lượng yêu cầu từ một IP. Xoay vòng proxy cho phép vượt qua những giới hạn này.
- Kiểm tra nội dung phụ thuộc vào địa lý — kiểm tra cách trang web hiển thị cho người dùng từ các quốc gia khác nhau mà không cần rời khỏi văn phòng.
- Ẩn danh khi tự động hóa — che giấu IP thực của máy chủ khi thực hiện các yêu cầu hàng loạt đến các nguồn bên ngoài.
- Giám sát đối thủ — thu thập thường xuyên giá cả, danh mục, khuyến mãi từ các trang web đối thủ mà không có nguy cơ bị cấm.
Trong PHP, hai công cụ thường được sử dụng cho các yêu cầu HTTP là mở rộng tích hợp cURL và thư viện Guzzle HTTP Client. Cả hai đều hỗ trợ proxy HTTP, HTTPS, SOCKS4 và SOCKS5 — chúng ta sẽ xem xét từng cái một cách chi tiết.
Loại proxy nào nên chọn cho PHP
Trước khi viết mã, điều quan trọng là phải hiểu loại proxy nào phù hợp với nhiệm vụ của bạn. Các loại khác nhau có các đặc điểm khác nhau về tốc độ, độ tin cậy và mức độ ẩn danh.
| Loại proxy | Tốc độ | Độ ẩn danh | Tốt nhất cho |
|---|---|---|---|
| Proxy trung tâm dữ liệu | Rất cao | Trung bình | Phân tích mà không có hệ thống chống bot nghiêm ngặt, yêu cầu API |
| Proxy cư trú | Trung bình | Cao | Phân tích các trang web bảo mật, thị trường, dữ liệu địa lý |
| Proxy di động | Trung bình | Tối đa | Các trang web có bảo vệ chống bot nghiêm ngặt, mạng xã hội |
Đối với hầu hết các tác vụ phân tích dữ liệu từ các thị trường như Wildberries hoặc Ozon, lựa chọn tối ưu sẽ là proxy cư trú — IP của chúng thuộc về người dùng thực, điều này làm cho các yêu cầu gần như không thể phân biệt với lưu lượng truy cập trình duyệt thông thường. Proxy trung tâm dữ liệu sẽ phù hợp ở những nơi mà tốc độ quan trọng hơn sự kín đáo, và bảo vệ yếu.
Tất cả ba loại proxy đều hỗ trợ các giao thức HTTP/HTTPS và SOCKS5, vì vậy từ góc độ mã — cấu hình là giống nhau. Sự khác biệt chỉ nằm ở chuỗi kết nối.
Proxy trong cURL: cấu hình cơ bản
Mở rộng cURL có sẵn trong PHP và là cách tiêu chuẩn để thực hiện các yêu cầu HTTP trên máy chủ. Để kết nối proxy, có hai tùy chọn chính: CURLOPT_PROXY và CURLOPT_PROXYTYPE.
HTTP-proxy không cần xác thực
<?php
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => 'https://httpbin.org/ip',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_TIMEOUT => 30,
// Chỉ định địa chỉ proxy
CURLOPT_PROXY => '185.199.100.1:8080',
// Loại proxy: HTTP (mặc định)
CURLOPT_PROXYTYPE => CURLPROXY_HTTP,
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo "Mã HTTP: $httpCode\n";
echo $response;
Ở đây CURLOPT_PROXY nhận một chuỗi theo định dạng host:port. Đối với lưu lượng HTTPS qua HTTP-proxy, cURL tự động sử dụng phương pháp CONNECT — tunneling, vì vậy nội dung của yêu cầu vẫn được mã hóa.
Các tùy chọn hữu ích của cURL cho làm việc với proxy
| Tùy chọn | Mô tả |
|---|---|
CURLOPT_PROXY |
Địa chỉ máy chủ proxy (host:port) |
CURLOPT_PROXYTYPE |
Loại: CURLPROXY_HTTP, CURLPROXY_SOCKS4, CURLPROXY_SOCKS5 |
CURLOPT_PROXYUSERPWD |
Tên đăng nhập và mật khẩu theo định dạng user:password |
CURLOPT_HTTPPROXYTUNNEL |
Bật tunneling qua HTTP CONNECT |
CURLOPT_SSL_VERIFYPEER |
Kiểm tra chứng chỉ SSL (false — tắt) |
CURLOPT_TIMEOUT |
Thời gian chờ yêu cầu tính bằng giây |
CURLOPT_CONNECTTIMEOUT |
Thời gian chờ kết nối đến proxy |
Xác thực và SOCKS5 trong cURL
Hầu hết các proxy thương mại yêu cầu xác thực bằng tên đăng nhập và mật khẩu. Ngoài ra, SOCKS5 là giao thức ưu tiên khi cần ẩn danh hoàn toàn, vì nó không thêm các tiêu đề như X-Forwarded-For, có thể tiết lộ việc sử dụng proxy.
HTTP-proxy với tên đăng nhập và mật khẩu
<?php
$proxyHost = '185.199.100.1';
$proxyPort = '8080';
$proxyUser = 'your_login';
$proxyPass = 'your_password';
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => 'https://httpbin.org/ip',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_CONNECTTIMEOUT => 10,
// Proxy với xác thực
CURLOPT_PROXY => "$proxyHost:$proxyPort",
CURLOPT_PROXYTYPE => CURLPROXY_HTTP,
CURLOPT_PROXYUSERPWD => "$proxyUser:$proxyPass",
// Tunneling cho HTTPS
CURLOPT_HTTPPROXYTUNNEL => true,
// Tiêu đề trình duyệt để ngụy trang
CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
CURLOPT_HTTPHEADER => [
'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language: ru-RU,ru;q=0.9,en;q=0.8',
],
]);
$response = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Lỗi cURL: ' . curl_error($ch);
} else {
echo $response;
}
curl_close($ch);
SOCKS5-proxy trong cURL
<?php
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => 'https://httpbin.org/ip',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_PROXY => '185.199.100.1:1080',
// SOCKS5 với phân giải DNS qua proxy (được khuyến nghị!)
CURLOPT_PROXYTYPE => CURLPROXY_SOCKS5_HOSTNAME,
// Xác thực (nếu cần)
CURLOPT_PROXYUSERPWD => 'login:password',
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
💡 Quan trọng: SOCKS5 vs SOCKS5_HOSTNAME
Sử dụng CURLPROXY_SOCKS5_HOSTNAME thay vì CURLPROXY_SOCKS5. Sự khác biệt là, với SOCKS5_HOSTNAME, các yêu cầu DNS cũng đi qua proxy, điều này ngăn chặn rò rỉ DNS và tăng cường độ ẩn danh. Với SOCKS5 thông thường, DNS được phân giải cục bộ — điều này có thể tiết lộ IP thực của bạn.
Xoay vòng proxy trong cURL
Một proxy sẽ nhanh chóng bị chặn khi có nhiều yêu cầu. Chiến lược đúng đắn là có một nhóm proxy và luân phiên chúng. Dưới đây là một triển khai đơn giản nhưng hiệu quả:
<?php
class ProxyRotator
{
private array $proxies;
private int $currentIndex = 0;
public function __construct(array $proxies)
{
$this->proxies = $proxies;
shuffle($this->proxies); // Xáo trộn để có thứ tự ngẫu nhiên
}
/**
* Lấy proxy tiếp theo từ nhóm
*/
public function getNext(): string
{
$proxy = $this->proxies[$this->currentIndex];
$this->currentIndex = ($this->currentIndex + 1) % count($this->proxies);
return $proxy;
}
/**
* Lấy proxy ngẫu nhiên
*/
public function getRandom(): string
{
return $this->proxies[array_rand($this->proxies)];
}
}
// Danh sách proxy theo định dạng login:password@host:port
$proxyList = [
'user1:[email protected]:8080',
'user2:[email protected]:8080',
'user3:[email protected]:8080',
'user4:[email protected]:8080',
];
$rotator = new ProxyRotator($proxyList);
/**
* Hàm yêu cầu với việc tự động chọn proxy
*/
function fetchWithProxy(string $url, ProxyRotator $rotator): ?string
{
$proxyStr = $rotator->getNext();
// Phân tích chuỗi proxy
preg_match('/^(.+):(.+)@(.+):(\d+)$/', $proxyStr, $m);
[, $user, $pass, $host, $port] = $m;
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 20,
CURLOPT_CONNECTTIMEOUT => 8,
CURLOPT_PROXY => "$host:$port",
CURLOPT_PROXYTYPE => CURLPROXY_HTTP,
CURLOPT_PROXYUSERPWD => "$user:$pass",
CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)',
CURLOPT_SSL_VERIFYPEER => false,
]);
$response = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
error_log("Proxy $host:$port không khả dụng: $error");
return null;
}
return $response;
}
// Ví dụ: phân tích 10 trang với việc xoay vòng proxy
$urls = [
'https://example.com/page/1',
'https://example.com/page/2',
'https://example.com/page/3',
// ...
];
foreach ($urls as $url) {
$html = fetchWithProxy($url, $rotator);
if ($html) {
echo "Đã nhận: " . strlen($html) . " byte\n";
}
usleep(500000); // Tạm dừng 0.5 giây giữa các yêu cầu
}
Lưu ý về usleep(500000) — thời gian tạm dừng giữa các yêu cầu là rất quan trọng. Ngay cả khi có việc xoay vòng proxy, các yêu cầu quá thường xuyên có thể dẫn đến việc bị chặn do các mẫu hành vi. Khoảng thời gian được khuyến nghị — từ 500 ms đến 2 giây tùy thuộc vào trang web.
Proxy trong Guzzle HTTP Client: cấu hình cơ bản
Guzzle là một thư viện PHP mạnh mẽ cho các yêu cầu HTTP, được sử dụng trong hầu hết các framework PHP hiện đại (Laravel, Symfony). Nó cung cấp một API dễ sử dụng và dễ đọc hơn so với cURL thuần túy, hỗ trợ các yêu cầu bất đồng bộ, middleware và xử lý lỗi thuận tiện.
Cài đặt qua Composer
composer require guzzlehttp/guzzle
HTTP-proxy không cần xác thực
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;
$client = new Client([
// URL cơ bản (tùy chọn)
'base_uri' => 'https://httpbin.org',
// Cài đặt mặc định cho tất cả các yêu cầu
'timeout' => 30,
'connect_timeout' => 10,
// Proxy cho tất cả các yêu cầu của client
'proxy' => 'http://185.199.100.1:8080',
]);
$response = $client->get('/ip');
echo $response->getStatusCode() . "\n"; // 200
echo $response->getBody() . "\n"; // {"origin": "185.199.100.1"}
Trong Guzzle, proxy được chỉ định qua tùy chọn proxy theo định dạng URL. Điều này trực quan hơn so với cURL. Proxy có thể được chỉ định ở cấp độ client (cho tất cả các yêu cầu) hoặc cho từng yêu cầu riêng lẻ.
HTTP-proxy với xác thực
<?php
use GuzzleHttp\Client;
$login = 'your_login';
$password = 'your_password';
$host = '185.199.100.1';
$port = '8080';
$client = new Client([
'timeout' => 30,
]);
// Proxy với xác thực được truyền theo định dạng URL
$response = $client->get('https://httpbin.org/ip', [
'proxy' => "http://$login:$password@$host:$port",
'headers' => [
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9',
],
]);
echo $response->getBody();
Định dạng URL proxy trong Guzzle: scheme://user:password@host:port. Đối với HTTP-proxy, sử dụng http://, đối với SOCKS5 — socks5://.
Làm việc nâng cao với Guzzle: thời gian chờ, tiêu đề, SOCKS5
Hãy xem xét các kịch bản phức tạp hơn: các proxy khác nhau cho HTTP và HTTPS, SOCKS5, tắt kiểm tra SSL và cấu hình tiêu đề để mô phỏng trình duyệt.
Các proxy khác nhau cho HTTP và HTTPS
<?php
use GuzzleHttp\Client;
$client = new Client([
'timeout' => 30,
'proxy' => [
// Proxy cho các yêu cầu HTTP
'http' => 'http://login:[email protected]:8080',
// Proxy cho các yêu cầu HTTPS
'https' => 'http://login:[email protected]:8080',
// Các ngoại lệ — những máy chủ này đi mà không có proxy
'no' => ['localhost', '127.0.0.1', '.internal.corp'],
],
]);
SOCKS5 trong Guzzle
<?php
use GuzzleHttp\Client;
// Đối với SOCKS5 trong Guzzle cần một gói bổ sung
// composer require clue/socks-react (hoặc sử dụng curl handler)
$client = new Client([
'timeout' => 30,
'proxy' => 'socks5://login:[email protected]:1080',
'curl' => [
CURLOPT_PROXYTYPE => CURLPROXY_SOCKS5_HOSTNAME,
],
]);
$response = $client->get('https://httpbin.org/ip');
echo $response->getBody();
Cấu hình đầy đủ với tiêu đề trình duyệt
<?php
use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;
$client = new Client([
'timeout' => 30,
'connect_timeout' => 10,
'verify' => false, // Tắt kiểm tra SSL (cho gỡ lỗi)
'allow_redirects' => [
'max' => 5,
'strict' => false,
'referer' => true,
'protocols' => ['http', 'https'],
],
'headers' => [
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language' => 'ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7',
'Accept-Encoding' => 'gzip, deflate, br',
'Cache-Control' => 'no-cache',
'Connection' => 'keep-alive',
],
]);
$response = $client->get('https://example.com/catalog', [
'proxy' => 'http://login:[email protected]:8080',
]);
$statusCode = $response->getStatusCode();
$body = (string) $response->getBody();
echo "Trạng thái: $statusCode, Kích thước: " . strlen($body) . " byte\n";
⚠️ Về verify => false
Tắt kiểm tra SSL ('verify' => false) chỉ được phép trong quá trình gỡ lỗi hoặc làm việc với các dịch vụ nội bộ. Trong mã sản xuất, luôn để kiểm tra SSL được bật, nếu không bạn sẽ dễ bị tấn công kiểu man-in-the-middle.
Xoay vòng proxy trong Guzzle
Trong Guzzle, việc xoay vòng rất dễ dàng thực hiện thông qua middleware — lớp trung gian, mà chặn mỗi yêu cầu và thêm proxy vào nó. Điều này thanh lịch hơn so với việc truyền proxy thủ công trong mỗi lần gọi.
<?php
use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
use Psr\Http\Message\RequestInterface;
/**
* Middleware cho việc tự động xoay vòng proxy
*/
function proxyRotationMiddleware(array $proxies): callable
{
$index = 0;
$total = count($proxies);
return Middleware::mapRequest(
function (RequestInterface $request) use ($proxies, &$index, $total) {
$proxy = $proxies[$index % $total];
$index++;
// Thêm proxy vào thuộc tính của yêu cầu
// (truyền qua options trong handler)
return $request->withHeader('X-Selected-Proxy', $proxy);
}
);
}
// Danh sách proxy
$proxies = [
'http://user1:[email protected]:8080',
'http://user2:[email protected]:8080',
'http://user3:[email protected]:8080',
];
// Phiên bản đơn giản: lớp bọc quanh Guzzle với việc xoay vòng
class GuzzleWithRotation
{
private Client $client;
private array $proxies;
private int $index = 0;
public function __construct(array $proxies, array $clientConfig = [])
{
$this->proxies = $proxies;
$this->client = new Client($clientConfig);
}
public function get(string $url, array $options = []): \GuzzleHttp\Psr7\Response
{
$options['proxy'] = $this->proxies[$this->index % count($this->proxies)];
$this->index++;
return $this->client->get($url, $options);
}
public function post(string $url, array $options = []): \GuzzleHttp\Psr7\Response
{
$options['proxy'] = $this->proxies[$this->index % count($this->proxies)];
$this->index++;
return $this->client->post($url, $options);
}
}
// Sử dụng
$guzzle = new GuzzleWithRotation($proxies, [
'timeout' => 30,
'headers' => [
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)',
],
]);
$urls = [
'https://example.com/product/1',
'https://example.com/product/2',
'https://example.com/product/3',
];
foreach ($urls as $url) {
try {
$response = $guzzle->get($url);
echo "OK [{$response->getStatusCode()}]: $url\n";
sleep(1);
} catch (\Exception $e) {
echo "Lỗi: " . $e->getMessage() . "\n";
}
}
Xử lý lỗi và gỡ lỗi
Khi làm việc với proxy, lỗi là điều không thể tránh khỏi: proxy có thể không khả dụng, phản hồi chậm, hoặc trang web mục tiêu có thể trả về lỗi. Quan trọng là phải xử lý tất cả các tình huống này một cách hợp lý.
Xử lý lỗi trong cURL
<?php
function fetchWithErrorHandling(string $url, string $proxy): array
{
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 20,
CURLOPT_CONNECTTIMEOUT => 8,
CURLOPT_PROXY => $proxy,
CURLOPT_PROXYTYPE => CURLPROXY_HTTP,
]);
$body = curl_exec($ch);
$errno = curl_errno($ch);
$error = curl_error($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$totalTime = curl_getinfo($ch, CURLINFO_TOTAL_TIME);
curl_close($ch);
// Mã lỗi cURL cho proxy
$proxyErrors = [
CURLE_COULDNT_CONNECT => 'Không thể kết nối đến proxy',
CURLE_OPERATION_TIMEDOUT => 'Thời gian chờ kết nối đến proxy',
CURLE_RECV_ERROR => 'Lỗi nhận dữ liệu',
CURLE_SSL_CONNECT_ERROR => 'Lỗi SSL qua proxy',
];
if ($errno) {
$message = $proxyErrors[$errno] ?? "Lỗi cURL #$errno: $error";
return ['success' => false, 'error' => $message, 'code' => $errno];
}
if ($httpCode >= 400) {
return ['success' => false, 'error' => "HTTP $httpCode", 'code' => $httpCode];
}
return [
'success' => true,
'body' => $body,
'code' => $httpCode,
'time' => round($totalTime, 3),
];
}
// Sử dụng với các lần thử lại
function fetchWithRetry(string $url, array $proxies, int $maxRetries = 3): ?string
{
foreach ($proxies as $proxy) {
for ($attempt = 1; $attempt <= $maxRetries; $attempt++) {
$result = fetchWithErrorHandling($url, $proxy);
if ($result['success']) {
echo "Thành công qua $proxy (cố gắng $attempt, {$result['time']}s)\n";
return $result['body'];
}
echo "Lỗi qua $proxy: {$result['error']}\n";
if ($attempt < $maxRetries) {
sleep(2); // Tạm dừng trước khi thử lại
}
}
}
return null; // Tất cả các proxy không hoạt động
}
Xử lý lỗi trong Guzzle
<?php
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Exception\ServerException;
use GuzzleHttp\Exception\ClientException;
$client = new Client(['timeout' => 30]);
$proxies = [
'http://user1:[email protected]:8080',
'http://user2:[email protected]:8080',
];
function fetchGuzzleWithFallback(Client $client, string $url, array $proxies): ?string
{
foreach ($proxies as $proxy) {
try {
$response = $client->get($url, [
'proxy' => $proxy,
'timeout' => 20,
]);
return (string) $response->getBody();
} catch (ConnectException $e) {
// Proxy không khả dụng hoặc thời gian chờ kết nối
echo "Proxy không khả dụng ($proxy): " . $e->getMessage() . "\n";
} catch (ClientException $e) {
// HTTP 4xx — lỗi của khách hàng (403, 404, 429)
$code = $e->getResponse()->getStatusCode();
echo "HTTP $code cho $url qua $proxy\n";
if ($code === 429) {
echo "Giới hạn tần suất — tạm dừng 5 giây\n";
sleep(5);
}
} catch (ServerException $e) {
// HTTP 5xx — lỗi của máy chủ
echo "Lỗi máy chủ: " . $e->getResponse()->getStatusCode() . "\n";
} catch (RequestException $e) {
// Các lỗi khác của yêu cầu
echo "Lỗi yêu cầu: " . $e->getMessage() . "\n";
}
}
return null;
}
cURL vs Guzzle: chọn cái nào
Cả hai công cụ đều hoạt động tuyệt vời với proxy, nhưng có những điểm mạnh khác nhau. Dưới đây là so sánh theo các tiêu chí chính:
| Tiêu chí | cURL | Guzzle |
|---|---|---|
| Cài đặt | ✅ Tích hợp sẵn trong PHP | ⚠️ Cần Composer |
| Độ dễ đọc của mã | ⚠️ Nhiều tùy chọn, dài dòng | ✅ API sạch, dễ sử dụng |
| Hiệu suất | ✅ Nhanh hơn một chút (không có lớp bọc) | ✅ So sánh, có async |
| Yêu cầu bất đồng bộ | ⚠️ curl_multi (khó) | ✅ Hỗ trợ tích hợp |
| Middleware / hooks | ❌ Không có | ✅ HandlerStack, Middleware |
| Hỗ trợ SOCKS5 | ✅ Tự nhiên | ✅ Qua curl handler |
| Xử lý lỗi | ⚠️ Mã lỗi thủ công | ✅ Ngoại lệ với các loại |
| Tích hợp vào Laravel/Symfony | ⚠️ Thủ công | ✅ Hỗ trợ tự nhiên |
| Phù hợp cho | Các script đơn giản, không có phụ thuộc | Dự án trên các framework, logic phức tạp |
Khuyến nghị: Nếu bạn đang viết một script đơn giản hoặc làm việc trên hosting không có Composer — hãy sử dụng cURL. Đối với các dự án trên Laravel, Symfony hoặc bất kỳ ứng dụng PHP hiện đại nào — Guzzle sẽ tiện lợi hơn nhiều và cung cấp nhiều khả năng mở rộng hơn.
🚀 Danh sách kiểm tra nhanh trước khi khởi chạy
- ✅ Kiểm tra xem proxy có hoạt động không:
curl -x http://login:pass@host:port https://httpbin.org/ip - ✅ Đặt thời gian chờ:
timeoutvàconnect_timeout - ✅ Thêm User-Agent thực tế
- ✅ Thực hiện các khoảng dừng giữa các yêu cầu (tối thiểu 500 ms)
- ✅ Dự phòng xử lý lỗi và fallback sang proxy khác
- ✅ Đối với SOCKS5, hãy sử dụng CURLPROXY_SOCKS5_HOSTNAME (không phải SOCKS5)
- ✅ Không tắt verify SSL trong môi trường sản xuất
Kết luận
Thiết lập proxy trong PHP là một nhiệm vụ không khó nếu biết các tùy chọn và định dạng đúng. Đối với các tác vụ cơ bản, cURL với CURLOPT_PROXY và CURLOPT_PROXYUSERPWD là đủ. Đối với các dự án trên framework, Guzzle cung cấp một API dễ sử dụng hơn, các ngoại lệ có kiểu và hỗ trợ middleware cho việc xoay vòng proxy.
Các nguyên tắc chính để hoạt động đáng tin cậy: sử dụng SOCKS5 với phân giải DNS qua proxy (CURLPROXY_SOCKS5_HOSTNAME), luôn đặt thời gian chờ, thêm các khoảng dừng giữa các yêu cầu và thực hiện xoay vòng proxy cho các tác vụ quy mô lớn. Xử lý lỗi với fallback sang proxy khác là một phần bắt buộc của bất kỳ mã sản xuất nào.
```