Применение cURL в PHP для взаимодействия с HTTP сервисами
Основы работы с cURL в PHP
Библиотека cURL (Client URL) предоставляет широкие возможности для отправки HTTP запросов и получения ответов. В PHP функции cURL позволяют имитировать браузер, управлять заголовками, куками, обрабатывать редиректы и выполнять асинхронные запросы.
Как реализовать универсальную функцию для HTTP запросов с обработкой ошибок?
Наиболее эффективным решением является создание отдельной функции, которая принимает параметры запроса (метод, URL, данные, заголовки, настройки таймаута и SSL) и возвращает ответ в удобном формате.
function curl_request($url, $method = 'GET', $data = null, $headers = [], $options = []) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_TIMEOUT, $options['timeout'] ?? 30);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, $options['follow_redirects'] ?? true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $options['verify_ssl'] ?? true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, $options['verify_ssl'] ?? true ? 2 : 0);
if ($headers) {
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
}
if ($method === 'POST') {
curl_setopt($ch, CURLOPT_POST, true);
if ($data !== null) {
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}
} elseif ($method === 'PUT') {
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
if ($data !== null) {
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}
} elseif ($method !== 'GET') {
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
if ($data !== null) {
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}
}
$response = curl_exec($ch);
$error = curl_error($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($error) {
return ['error' => $error, 'http_code' => $http_code, 'response' => $response];
}
return ['http_code' => $http_code, 'response' => $response];
}
Index php curl (curl в php)
Пояснение шагов:
- Инициализация сеанса cURL через
curl_init. - Установка базовых опций: возврат результата в переменную, таймаут, следование редиректам, проверка SSL.
- Передача заголовков, если они заданы.
- Выбор метода запроса: GET, POST, PUT, DELETE и другие.
- Выполнение запроса и обработка ошибок.
- Закрытие сеанса и возврат массива с кодом ответа, телом и возможной ошибкой.
Типичные проблемы и их решения:
- Ошибка SSL 60: сертификат не доверенный. Решение: установить
CURLOPT_SSL_VERIFYPEER = falseили указать путь к CA bundle черезCURLOPT_CAINFO. - Таймаут (ошибка 28): сервер долго отвечает. Увеличить
CURLOPT_TIMEOUTилиCURLOPT_CONNECTTIMEOUT. - Пустой ответ: возможно редирект без разрешения. Проверить
CURLOPT_FOLLOWLOCATION. - Ошибка 52: сервер закрыл соединение. Проверить правильность URL и доступность сервера.
Как отправить простой GET запрос с параметрами?
Цель: получить данные от удаленного API, передав параметры в URL.
$url = 'https://api.example.com/users';
$params = ['page' => 1, 'limit' => 10];
$url .= '?' . http_build_query($params);
$result = curl_request($url, 'GET');
if ($result['http_code'] === 200) {
$data = json_decode($result['response'], true);
// обработка данных
} else {
echo 'Ошибка: ' . $result['http_code'];
}
Как передать данные через POST запрос в формате JSON?
Цель: отправить структурированные данные в теле запроса (например, для REST API).
$data = ['name' => 'Иван', 'email' => 'ivan@example.com'];
$json = json_encode($data);
$url = 'https://api.example.com/users';
$headers = ['Content-Type: application/json'];
$result = curl_request($url, 'POST', $json, $headers);
Проблема: если не указать заголовок Content-Type: application/json, сервер может не распознать JSON. Также важно правильно кодировать UTF-8.
Как выполнить POST запрос с URL-кодированными данными (form-data)?
Цель: имитация отправки HTML формы.
$form_data = ['username' => 'user', 'password' => 'pass'];
$url = 'https://example.com/login';
$result = curl_request($url, 'POST', http_build_query($form_data));
Обратите внимание, что http_build_query автоматически кодирует данные.
Как загрузить файл на сервер через multipart/form-data?
Цель: отправка файла вместе с другими полями (например, аватар).
$file_path = '/path/to/file.jpg';
$ch = curl_init('https://example.com/upload');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = [
'file' => new CURLFile($file_path, 'image/jpeg', 'avatar.jpg'),
'description' => 'Мой аватар'
];
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$response = curl_exec($ch);
curl_close($ch);
Важно:
Если используется CURLFile, PHP автоматически установит Content-Type: multipart/form-data. Не нужно добавлять заголовок вручную.
Ошибка: "Only arrays and Traversables can be unpacked" может возникнуть при передаче файла через CURLOPT_POSTFIELDS в старых версиях PHP. Решение: использовать curl_file_create вместо new CURLFile.
Как установить пользовательские заголовки (User-Agent, Authorization)?
Цель: имитация браузера или авторизация через токен.
$url = 'https://api.example.com/protected';
$token = 'Bearer abc123';
$headers = [
'Authorization: ' . $token,
'User-Agent: MyApp/1.0',
'Accept: application/json'
];
$result = curl_request($url, 'GET', null, $headers);
Как управлять cookie в cURL (сохранение и отправка)?
Цель: поддержка сессии между запросами.
$cookie_file = '/tmp/cookies.txt';
$ch = curl_init('https://example.com/login');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_file);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_file);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, ['user' => 'admin', 'pass' => '123']);
$response = curl_exec($ch);
curl_close($ch);
// последующие запросы будут использовать те же cookies
Проблема: файл cookie может быть недоступен для записи. Убедиться в правах доступа или использовать временную директорию.
Как выполнить запрос через прокси-сервер?
Цель: обход ограничений или анонимизация.
$ch = curl_init('https://httpbin.org/ip');
curl_setopt($ch, CURLOPT_PROXY, 'http://proxy.example.com:3128');
curl_setopt($ch, CURLOPT_PROXYUSERPWD, 'user:pass');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
Типы прокси:
SOAP, HTTP, SOCKS5. Для SOCKS5 используйтеCURLOPT_PROXYTYPE = CURLPROXY_SOCKS5.
Как обработать редиректы и получить финальный URL?
Цель: узнать, куда привел редирект (например, после сокращения ссылки).
$ch = curl_init('http://bit.ly/example');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
$response = curl_exec($ch);
$final_url = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
curl_close($ch);
echo 'Финальный URL: ' . $final_url;
Как выполнить несколько запросов параллельно (cURL Multi)?
Цель: ускорение загрузки данных с нескольких серверов одновременно.
$urls = ['https://api1.com', 'https://api2.com', 'https://api3.com'];
$mh = curl_multi_init();
$handles = [];
foreach ($urls as $i => $url) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_multi_add_handle($mh, $ch);
$handles[$i] = $ch;
}
$running = null;
do {
curl_multi_exec($mh, $running);
curl_multi_select($mh);
} while ($running > 0);
foreach ($handles as $ch) {
$response = curl_multi_getcontent($ch);
// обработка ответа
curl_multi_remove_handle($mh, $ch);
curl_close($ch);
}
curl_multi_close($mh);
Проблема: неконтролируемое количество одновременных соединений. Можно ограничить через CURLOPT_CONNECTTIMEOUT или использовать curl_multi_select для ожидания.
Как отлаживать запросы cURL (вывод заголовков и деталей)?
Цель: увидеть что отправляется и приходит для диагностики.
$ch = curl_init('https://example.com');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_VERBOSE, true);
$verbose = fopen('php://temp', 'w+');
curl_setopt($ch, CURLOPT_STDERR, $verbose);
$response = curl_exec($ch);
rewind($verbose);
$verbose_output = stream_get_contents($verbose);
fclose($verbose);
echo 'Отладочная информация:';
echo '<pre>' . htmlspecialchars($verbose_output) . '</pre>';
curl_close($ch);
Также можно использовать CURLOPT_HEADER = true для включения заголовков ответа в тело.
Совместное использование cookie между запросами через curl_share
Для экономии ресурсов при множественных запросах к одному домену можно использовать общий cookie-стор.
$share = curl_share_init();
curl_share_setopt($share, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);
$ch1 = curl_init('https://example.com/login');
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch1, CURLOPT_POST, true);
curl_setopt($ch1, CURLOPT_POSTFIELDS, 'user=admin&pass=123');
curl_setopt($ch1, CURLOPT_SHARE, $share);
$result1 = curl_exec($ch1);
$ch2 = curl_init('https://example.com/profile');
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch2, CURLOPT_SHARE, $share);
$result2 = curl_exec($ch2);
curl_close($ch1);
curl_close($ch2);
curl_share_close($share);
Результат:
Второй запрос получит содержимое профиля уже авторизованного пользователя, так как cookies были общими.(Пример вывода: HTML страница профиля)
Скачивание большого файла напрямую в файловую систему
Избегаем загрузки всего файла в память, используя CURLOPT_FILE.
$url = 'https://example.com/file.zip';
$output_file = fopen('download.zip', 'wb');
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_FILE, $output_file);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_exec($ch);
if (curl_error($ch)) {
echo 'Ошибка: ' . curl_error($ch);
} else {
echo 'Файл скачан успешно';
}
curl_close($ch);
fclose($output_file);
Результат:
Файл будет сохранен на диск без использования дополнительной памяти.Файл скачан успешно
Отправка данных частями с помощью callback функции
Полезно для передачи больших объёмов данных без предварительной загрузки.
$data = 'abcdefghijklmnopqrstuvwxyz';
$offset = 0;
$ch = curl_init('https://httpbin.org/post');
curl_setopt($ch, CURLOPT_PUT, true);
curl_setopt($ch, CURLOPT_READFUNCTION, function($ch, $fd, $length) use ($data, &$offset) {
$remaining = substr($data, $offset, $length);
$offset += strlen($remaining);
return $remaining;
});
curl_setopt($ch, CURLOPT_INFILESIZE, strlen($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Результат:
Сервер получит строку целиком как PUT данные.
{
"data": "abcdefghijklmnopqrstuvwxyz",
...
}
Обработка заголовков ответа без их включения в тело
Позволяет прочитать заголовки до получения полного ответа.
$headers = [];
$ch = curl_init('https://example.com');
curl_setopt($ch, CURLOPT_HEADERFUNCTION, function($ch, $header) use (&$headers) {
$headers[] = $header;
return strlen($header);
});
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$body = curl_exec($ch);
curl_close($ch);
print_r($headers);
Результат:
Массив заголовков ответа будет выведен.
Array
(
[0] => HTTP/2 200
[1] => Content-Type: text/html
[2] => Date: ...
)
Работа с cookies через массив (без записи на диск)
Удобно, когда нужно быстро задать или прочитать cookies.
$ch = curl_init('https://example.com');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIELIST, 'Set-Cookie: session_id=abc123; path=/');
curl_exec($ch);
$cookies = curl_getinfo($ch, CURLINFO_COOKIELIST);
print_r($cookies);
curl_close($ch);
Результат:
Массив cookie, которые были установлены сервером и отправлены.
Array
(
[0] => example.com\tFALSE\t/\tFALSE\t0\tsession_id\tabc123
)