Клиентские HTTP запросы в PHP: от основ до продвинутых техник

Раздел: Веб-разработка -> API

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

Веб-клиент на PHP (например, cURL) - comments

En
Php web client (php)