Функция cURL в PHP: от базовых HTTP запросов до продвинутой настройки
Работа с cURL в PHP: основные возможности
Как выполнить простой GET запрос с помощью cURL и получить ответ сервера?
Библиотека cURL (Client URL) в PHP предоставляет мощный инструмент для отправки HTTP запросов и обмена данными с удалёнными серверами. Самая распространённая задача – получение содержимого внешнего ресурса. Ниже приведён базовый пример инициализации, настройки и выполнения запроса.
<?php
// Инициализация сеанса cURL
$ch = curl_init();
// Установка URL
curl_setopt($ch, CURLOPT_URL, "https://api.example.com/data");
// Возвращать результат в виде строки, а не выводить напрямую
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Выполнение запроса
$response = curl_exec($ch);
// Проверка на ошибки
if (curl_errno($ch)) {
die("Ошибка cURL: " . curl_error($ch));
}
// Закрытие сеанса
curl_close($ch);
echo $response;
?>
Curl function php (функция curl в php)
Здесь функция curl_init() создаёт новый сеанс, curl_setopt() задаёт параметры запроса (URL, возврат результата), а curl_exec() выполняет запрос. В случае ошибки curl_errno() и curl_error() помогут диагностировать проблему.
Типичная ошибка: Не включён модуль cURL в PHP (вызов curl_init() приводит к фатальной ошибке). Решение: Убедиться, что в php.ini строка extension=curl раскомментирована, или установить пакет php-curl.
Ещё одна распространённая проблема – ошибка SSL при запросах к HTTPS ресурсам (certificate verify failed). В этом случае для разработки можно временно отключить проверку SSL (не рекомендуется для продакшена):
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
Как отправить POST запрос с данными формы?
Для отправки данных методом POST используется опция CURLOPT_POST и CURLOPT_POSTFIELDS. Данные передаются в виде строки запроса или ассоциативного массива.
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://api.example.com/submit");
curl_setopt($ch, CURLOPT_POST, true);
$postData = array('name' => 'Иван', 'email' => 'ivan@example.com');
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
?>
Ошибка: Если передавать массив напрямую, cURL автоматически установит Content-Type: multipart/form-data. При использовании http_build_query() тип будет application/x-www-form-urlencoded. Выбор зависит от требований сервера.
Как передать заголовки HTTP, включая авторизацию Bearer?
Для установки пользовательских заголовков используется опция CURLOPT_HTTPHEADER. В примере ниже добавляется заголовок Authorization с токеном.
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://api.example.com/secure");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$headers = [
"Authorization: Bearer YOUR_TOKEN",
"Content-Type: application/json"
];
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($ch);
curl_close($ch);
?>
Аналогичным образом можно передать Basic авторизацию (логин:пароль) через CURLOPT_USERPWD:
curl_setopt($ch, CURLOPT_USERPWD, "username:password");
Как отправлять JSON данные в теле запроса?
При отправке JSON необходимо вручную задать заголовок Content-Type: application/json и передать строку JSON через CURLOPT_POSTFIELDS.
<?php
$jsonData = json_encode(['key1' => 'value1', 'key2' => 'value2']);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://api.example.com/json");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Content-Type: application/json",
"Content-Length: " . strlen($jsonData)
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
?>
Как обрабатывать cookies и сессии?
Для сохранения и отправки cookies используются CURLOPT_COOKIEJAR (файл для записи cookie) и CURLOPT_COOKIEFILE (файл для чтения).
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://example.com/login");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, '/tmp/cookies.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/cookies.txt');
$response = curl_exec($ch);
curl_close($ch);
?>
Проблема: Права доступа к файлу cookies.txt могут не позволить PHP записывать или читать его. Следует указать путь к файлу с корректными правами (например, в директории /tmp или другой доступной для записи).
Как установить тайм-аут запроса и лимит времени?
Для ограничения времени выполнения запроса применяются CURLOPT_TIMEOUT (секунды) и CURLOPT_CONNECTTIMEOUT (время на соединение).
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
Ошибка: При превышении тайм-аута cURL возвращает ошибку с кодом CURLE_OPERATION_TIMEDOUT (28). Можно обработать её через curl_errno().
Как выполнить GET запрос с параметрами URL (query string)?
Параметры в URL передаются вручную или с помощью http_build_query().
$params = ['page' => 1, 'limit' => 20];
$url = "https://api.example.com/data?" . http_build_query($params);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
Как загрузить файл на сервер через cURL?
Для загрузки файла с типом multipart/form-data используется массив в CURLOPT_POSTFIELDS, где значение – путь к файлу с префиксом @ (до PHP 5.5) или объект CURLFile.
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://api.example.com/upload");
curl_setopt($ch, CURLOPT_POST, true);
$post = [
'file' => new CURLFile('/path/to/file.pdf'),
'description' => 'Пример файла'
];
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
?>
Как использовать прокси-сервер для запросов?
Для работы через прокси используются CURLOPT_PROXY (адрес:порт) и опционально CURLOPT_PROXYUSERPWD для авторизации.
curl_setopt($ch, CURLOPT_PROXY, "http://proxy.example.com:8080");
curl_setopt($ch, CURLOPT_PROXYUSERPWD, "user:pass");
Проблема: Если прокси требует аутентификации, а она не указана, запрос может завершиться с кодом 407. Следует также использовать CURLOPT_HTTPPROXYTUNNEL при работе с HTTPS через HTTP прокси.
Как выполнить несколько запросов одновременно (мульти-curl)?
Для параллельных запросов используется curl_multi_* функции. Это ускоряет работу, когда необходимо обратиться к нескольким ресурсам сразу.
<?php
$urls = [
"https://api1.example.com",
"https://api2.example.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;
}
$active = null;
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
while ($active && $mrc == CURLM_OK) {
if (curl_multi_select($mh) == -1) {
usleep(100);
}
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
foreach ($channels as $ch) {
$response = curl_multi_getcontent($ch);
echo "Response from channel: " . $response . "\n";
curl_multi_remove_handle($mh, $ch);
curl_close($ch);
}
curl_multi_close($mh);
?>
Сложность: Код мульти-курла требует правильного управления циклами. Типичная ошибка – забыть вызвать curl_multi_select(), что приводит к 100% загрузке CPU. Рекомендуется использовать готовые обёртки (Guzzle, ReactPHP) для упрощения.
Как получить информацию о выполнении запроса (статус, размер, тип)?
После выполнения запроса можно вызвать curl_getinfo() с опциональной константой для получения отдельных метаданных.
$info = curl_getinfo($ch);
echo "HTTP статус: " . $info['http_code'];
echo "Размер ответа: " . $info['size_download'];
echo "Content-Type: " . $info['content_type'];
Также можно получить только одну характеристику, передав константу, например curl_getinfo($ch, CURLINFO_HTTP_CODE).
Как обработать редиректы (302, 301) автоматически?
Для следования за редиректами используется CURLOPT_FOLLOWLOCATION и CURLOPT_MAXREDIRS для ограничения числа переходов.
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
Проблема: Если на сервере стоит open_basedir или safe_mode (старые версии PHP), опция CURLOPT_FOLLOWLOCATION может не работать. В таком случае редиректы следует обрабатывать вручную, считывая заголовок Location.
Как отправить запрос с методом PUT или DELETE?
Для нестандартных HTTP методов используется CURLOPT_CUSTOMREQUEST.
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
// Или DELETE
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
Каждый из этих вариантов подходит для различных сценариев интеграции с внешними API, парсинга данных, загрузки файлов и автоматизации взаимодействия с веб-сервисами.
Расширенные примеры использования cURL в PHP
Ниже приведены подробные примеры с кодом и результатами выполнения (предполагается работа с тестовым API).
Пример 1: GET запрос к публичному REST API с обработкой ошибок
<?php
function getUsers() {
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => "https://jsonplaceholder.typicode.com/users",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_HTTPHEADER => ['Accept: application/json']
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
return ['error' => "cURL error: $error"];
}
if ($httpCode !== 200) {
return ['error' => "HTTP code: $httpCode"];
}
return json_decode($response, true);
}
$result = getUsers();
print_r($result);
?>
Array
(
[0] => Array
(
[id] => 1
[name] => Leanne Graham
[username] => Bret
[email] => Sincere@april.biz
...
)
)
Пояснение: Функция curl_setopt_array() позволяет задать несколько параметров одним вызовом. Проверяется HTTP код ответа, выводится массив пользователей.
Пример 2: POST запрос с JSON и чтение ответа
<?php
$data = ['title' => 'foo', 'body' => 'bar', 'userId' => 1];
$json = json_encode($data);
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => "https://jsonplaceholder.typicode.com/posts",
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $json,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Content-Length: ' . strlen($json)
],
CURLOPT_RETURNTRANSFER => true
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo "HTTP status: $httpCode\n";
echo "Response: $response\n";
?>
HTTP status: 201
Response: {"title":"foo","body":"bar","userId":1,"id":101}
Пояснение: Успешный POST возвращает статус 201 и созданный объект с ID.
Пример 3: Загрузка файла на сервер с использованием CURLFile
<?php
$filePath = __DIR__ . '/test.txt';
file_put_contents($filePath, 'Hello, world!');
$cfile = new CURLFile($filePath, 'text/plain', 'test.txt');
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => "https://httpbin.org/post",
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => ['file' => $cfile],
CURLOPT_RETURNTRANSFER => true
]);
$response = curl_exec($ch);
curl_close($ch);
$decoded = json_decode($response, true);
echo "Uploaded file content: " . $decoded['files']['file'] . "\n";
unlink($filePath);
?>
Uploaded file content: Hello, world!
Пояснение: Используется специальный класс CURLFile (доступен с PHP 5.5), который корректно добавляет файл в multipart/form-data. После выполнения временный файл удаляется.
Пример 4: Асинхронные запросы через curl_multi с тайм-аутом
<?php
$urls = [
'https://httpbin.org/delay/2',
'https://httpbin.org/delay/1',
'https://httpbin.org/get'
];
$mh = curl_multi_init();
$handles = [];
foreach ($urls as $url) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_multi_add_handle($mh, $ch);
$handles[] = $ch;
}
$active = null;
do {
curl_multi_exec($mh, $active);
curl_multi_select($mh);
} while ($active);
foreach ($handles as $ch) {
$content = curl_multi_getcontent($ch);
$info = curl_getinfo($ch);
echo "URL: " . $info['url'] . " - HTTP " . $info['http_code'] . " - size: " . strlen($content) . "\n";
curl_multi_remove_handle($mh, $ch);
curl_close($ch);
}
curl_multi_close($mh);
?>
URL: https://httpbin.org/delay/2 - HTTP 200 - size: 310 URL: https://httpbin.org/delay/1 - HTTP 200 - size: 310 URL: https://httpbin.org/get - HTTP 200 - size: 286
Пояснение: Все три запроса выполняются параллельно, общее время выполнения равно самому медленному запросу (~2 секунды), а не сумме.
Пример 5: Работа с прокси и проверка SSL
<?php
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => "https://api64.ipify.org?format=json",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_PROXY => "http://proxy.example.com:3128",
CURLOPT_PROXYUSERPWD => "user:pass",
CURLOPT_PROXYTYPE => CURLPROXY_HTTP,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_CAINFO => "/etc/ssl/certs/ca-certificates.crt"
]);
$response = curl_exec($ch);
if (curl_errno($ch)) {
echo "Error: " . curl_error($ch);
} else {
$data = json_decode($response, true);
echo "Your public IP (via proxy): " . $data['ip'] . "\n";
}
curl_close($ch);
?>
Your public IP (via proxy): 123.456.789.0
Пояснение: Для проверки SSL сертификата используется файл центра сертификации. Прокси указывается со схемой http, тип - CURLPROXY_HTTP. Токен авторизации передаётся через CURLOPT_PROXYUSERPWD.
Пример 6: Использование cookie для сессионной авторизации
<?php
$cookieFile = tempnam(sys_get_temp_dir(), 'cookies');
// Шаг 1: авторизация
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => "https://httpbin.org/post",
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query(['username' => 'test', 'password' => 'secret']),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_COOKIEJAR => $cookieFile,
CURLOPT_COOKIEFILE => $cookieFile
]);
$response = curl_exec($ch);
curl_close($ch);
// Шаг 2: запрос с сохранённой сессией
$ch2 = curl_init();
curl_setopt_array($ch2, [
CURLOPT_URL => "https://httpbin.org/cookies",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_COOKIEFILE => $cookieFile
]);
$response2 = curl_exec($ch2);
curl_close($ch2);
echo "Cookies received:\n" . $response2 . "\n";
unlink($cookieFile);
?>
Cookies received:
{
"cookies": {
"username": "test",
"password": "secret"
}
}
Пояснение: После первого запроса сервер может установить cookie, которые сохраняются в файл. Второй запрос отправляет эти cookie обратно, что позволяет поддерживать сессию.
Пример 7: Отправка PATCH запроса с частичным обновлением
<?php
$data = ['title' => 'updated title'];
$json = json_encode($data);
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => "https://jsonplaceholder.typicode.com/posts/1",
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => $json,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_RETURNTRANSFER => true
]);
$response = curl_exec($ch);
curl_close($ch);
echo "Response: $response\n";
?>
Response: {"id":1,"title":"updated title","body":"...","userId":1}
Пояснение: CURLOPT_CUSTOMREQUEST позволяет отправлять любой HTTP метод, включая PATCH, DELETE, PUT. Тело запроса формируется как при POST.