Клиентские HTTP запросы в PHP: от основ до продвинутых техник
PHP веб-клиент позволяет отправлять HTTP запросы к внешним API и серверам. Рассмотрим различные подходы: встроенные функции и популярные библиотеки.
Основные подходы к реализации веб-клиента на PHP
Как выполнить HTTP запрос с помощью cURL?
cURL (Client URL Library) является расширением PHP, которое обычно включено в сборку. Оно поддерживает множество протоколов, куки, заголовки, аутентификацию и параллельные запросы.
Пример простого GET запроса:
$ch = curl_init('https://api.example.com/data');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
if (curl_errno($ch)) {
$error = curl_error($ch);
// обработать ошибку
}
curl_close($ch);
Php web client (веб-клиент на php (например, curl))
Для POST запроса добавляется CURLOPT_POST и CURLOPT_POSTFIELDS.
$ch = curl_init('https://api.example.com/submit');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query(['name' => 'value']),
CURLOPT_HTTPHEADER => ['Content-Type: application/x-www-form-urlencoded']
]);
$response = curl_exec($ch);
Типичные проблемы:
- Ошибка SSL: если сертификат самоподписанный, требуется отключить проверку (CURLOPT_SSL_VERIFYPEER = false), но это небезопасно.
- Таймаут: CURLOPT_TIMEOUT и CURLOPT_CONNECTTIMEOUT помогают избежать зависания.
- Работа с куками: включить CURLOPT_COOKIEJAR и CURLOPT_COOKIEFILE для сессий.
Когда достаточно простого GET запроса без дополнительных библиотек?
Для простых запросов можно использовать file_get_contents с потоковым контекстом. Этот метод не требует дополнительных расширений, но ограничен возможностями.
$context = stream_context_create([
'http' => [
'method' => 'GET',
'header' => 'User-Agent: MyClient'
]
]);
$response = file_get_contents('https://api.example.com/data', false, $context);
if ($response === false) {
// обработка ошибки
}
Для POST запроса создается контекст с method POST и content.
$options = [
'http' => [
'method' => 'POST',
'header' => 'Content-type: application/x-www-form-urlencoded',
'content' => http_build_query(['key' => 'val'])
]
];
$context = stream_context_create($options);
$result = file_get_contents('https://api.example.com/post', false, $context);
Проблемы: требуется включение директивы allow_url_fopen в php.ini, нет поддержки cookies, ограниченное управление заголовками, нет возможности асинхронных запросов.
Как создать гибкий HTTP клиент с поддержкой PSR-7?
Guzzle является самой популярной HTTP библиотекой для PHP. Она реализует PSR-7 (HTTP сообщения) и PSR-18 (HTTP клиент). Устанавливается через Composer.
Пример GET запроса:
require 'vendor/autoload.php';
use GuzzleHttp\Client;
$client = new Client();
$response = $client->get('https://api.example.com/data');
$body = $response->getBody()->getContents();
POST запрос с JSON:
$response = $client->post('https://api.example.com/submit', [
'json' => ['name' => 'value']
]);
$status = $response->getStatusCode();
Проблемы: требуется установка Composer, для простых проектов может быть избыточной. Необходимость обработки исключений (GuzzleHttp\Exception\ConnectException и др.)
Какие ещё библиотеки существуют для HTTP запросов?
Symfony HttpClient входит в Symfony компоненты, ReactPHP предоставляет асинхронные запросы для высоконагруженных систем, Httplug для абстракции. Выбор зависит от архитектуры проекта.
Расширенные примеры и сценарии
Пример 1: Параллельные запросы с curl_multi
$urls = ['https://api1.com', 'https://api2.com', 'https://api3.com'];
$mh = curl_multi_init();
$channels = [];
foreach ($urls as $i => $url) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_multi_add_handle($mh, $ch);
$channels[$i] = $ch;
}
$running = null;
do {
curl_multi_exec($mh, $running);
curl_multi_select($mh);
} while ($running > 0);
$results = [];
foreach ($channels as $i => $ch) {
$results[$i] = curl_multi_getcontent($ch);
curl_multi_remove_handle($mh, $ch);
curl_close($ch);
}
curl_multi_close($mh);
// $results содержит ответы от всех URL
// Результат: массив строк с ответами от каждого URL.
Пример 2: Загрузка файла через cURL
$file = new CURLFile('/path/to/file.png', 'image/png', 'file.png');
$ch = curl_init('https://api.example.com/upload');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => ['file' => $file, 'description' => 'My image']
]);
$response = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
// Ответ от сервера, например JSON с id загруженного файла.
Пример 3: Работа с куками и сессиями
$cookieJar = '/tmp/cookies.txt';
$ch = curl_init('https://example.com/login');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => 'username=user&pass=pass',
CURLOPT_COOKIEJAR => $cookieJar,
CURLOPT_COOKIEFILE => $cookieJar
]);
$response = curl_exec($ch);
curl_close($ch);
// Второй запрос авторизованного пользователя
$ch2 = curl_init('https://example.com/account');
curl_setopt_array($ch2, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_COOKIEFILE => $cookieJar
]);
$account = curl_exec($ch2);
curl_close($ch2);
// $account содержит HTML страницы аккаунта после успешного логина.
Пример 4: Использование прокси
$ch = curl_init('https://api.example.com');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_PROXY => 'http://proxy.example.com:8080',
CURLOPT_PROXYUSERPWD => 'user:password',
CURLOPT_PROXYTYPE => CURLPROXY_HTTP
]);
$data = curl_exec($ch);
curl_close($ch);
// Ответ через прокси.
Пример 5: Асинхронные запросы с Guzzle (промисы)
use GuzzleHttp\Client;
use GuzzleHttp\Promise;
$client = new Client();
$promises = [
'one' => $client->getAsync('https://api1.com'),
'two' => $client->getAsync('https://api2.com'),
];
$results = Promise\unwrap($promises);
foreach ($results as $key => $response) {
echo $key . ': ' . $response->getStatusCode();
}
// one: 200 // two: 200