Функция cURL в PHP: от базовых HTTP запросов до продвинутой настройки

Раздел: Сетевые функции -> 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.

Функция cURL в PHP - comments

En
Curl function php (php)