Функция curl_init в PHP: инициализация сеанса cURL для работы с HTTP

Раздел: PHP -> HTTP запросы с cURL

Инициализация cURL в PHP: функции curl_init и базовые возможности

Библиотека cURL предоставляет мощный инструмент для работы с HTTP протоколом. Центральная функция curl_init() создаёт новый сеанс (handle) для дальнейшей настройки и выполнения запроса. Без вызова этой функции невозможно воспользоваться остальными возможностями cURL. В статье рассматриваются различные способы использования curl_init, начиная от простейшего GET запроса и заканчивая обработкой ошибок и параллельными запросами.

Базовый способ: выполнение GET запроса

Основная задача curl_init - получение handle, который затем конфигурируется через curl_setopt и выполняется через curl_exec. Пример минимального GET запроса к публичному API:


<?php
$ch = curl_init('https://api.example.com/data');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
if ($response === false) {
    // ошибка
} else {
    echo $response;
}
curl_close($ch);
?>

После выполнения handle необходимо закрыть функцией curl_close для освобождения ресурсов. Опция CURLOPT_RETURNTRANSFER заставляет вернуть результат в переменную, а не выводить напрямую.

Возможные проблемы и их решения

  • Ошибка соединения (Could not resolve host) - проверьте правильность URL и доступность сети. Используйте curl_error($ch) для получения текста ошибки.
  • Пустой ответ - может быть вызван блокировкой сервера или отсутствием CURLOPT_RETURNTRANSFER (тогда результат сразу выводится в поток). Убедитесь, что включена опция.

Как выполнить POST запрос?

Для отправки данных методом POST требуется установить опцию CURLOPT_POST в true и передать тело запроса через CURLOPT_POSTFIELDS. Пример:


$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.example.com/login');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(['user' => 'admin', 'pass' => 'secret']));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);

Если передаётся массив, cURL автоматически устанавливает заголовок Content-Type: application/x-www-form-urlencoded. Для JSON данных нужно явно указать заголовки.

Типичная ошибка: пустой ответ при POST

Сервер может ожидать определённый формат данных. Проверьте, что CURLOPT_POSTFIELDS содержит строку или массив, а не объект. Используйте curl_getinfo($ch, CURLINFO_HTTP_CODE) для выяснения кода ответа.

Как обрабатывать ошибки cURL?

После вызова curl_exec стоит проверять возвращаемое значение на false. Для детальной диагностики используйте функции curl_error и curl_errno.


$ch = curl_init('http://example.com');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
if ($result === false) {
    $error = curl_error($ch);
    $errno = curl_errno($ch);
    // логирование или вывод
} else {
    // успешный ответ
}
curl_close($ch);

Ошибки, связанные с SSL

Если сервер использует самоподписанный сертификат, cURL может вернуть ошибку 60. Решение: временно отключить проверку сертификата (CURLOPT_SSL_VERIFYPEER = false), но в production лучше указать путь к CA-папке через CURLOPT_CAINFO.

Как установить таймаут на выполнение запроса?

Таймауты защищают скрипт от зависания при медленных ответах сервера. Используются опции CURLOPT_CONNECTTIMEOUT (время на соединение) и CURLOPT_TIMEOUT (общее время выполнения).


$ch = curl_init('http://slow.example.com');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); // 5 секунд на соединение
curl_setopt($ch, CURLOPT_TIMEOUT, 10);        // 10 секунд на весь запрос
$response = curl_exec($ch);
curl_close($ch);

Превышение времени выполнения

Если скрипт завершается по таймауту, ответ может быть неполным. Увеличьте значения в php.ini (max_execution_time) или используйте более длинные таймауты.

Как получить только заголовки ответа?

Опция CURLOPT_HEADER включает заголовки в тело ответа. Чтобы получить исключительно заголовки (без тела), установите CURLOPT_NOBODY в true.


$ch = curl_init('http://example.com');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);    // заголовки вместе с телом
curl_setopt($ch, CURLOPT_NOBODY, true);    // только заголовки
$headers = curl_exec($ch);
curl_close($ch);
echo $headers;

Такой приём полезен для проверки существования URL (получение кода 200) без загрузки содержимого.

Как передать заголовки запроса (User-Agent, Referer)?

Для установки кастомных заголовков используется опция CURLOPT_HTTPHEADER, которая принимает массив строк вида "Имя: значение".


$headers = [
    'User-Agent: CustomUserAgent/1.0',
    'Accept: application/json',
    'Referer: https://mysite.com'
];
$ch = curl_init('https://api.example.com');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);

Ошибка 400 при неправильном заголовке

Если сервер ожидает определённый формат (например, JSON), проверьте, что заголовок Content-Type установлен корректно. Для JSON: 'Content-Type: application/json'.

Как работать с автоперенаправлениями (редиректами)?

По умолчанию cURL не следует редиректам. Для автоматического перехода по Location нужно включить опцию CURLOPT_FOLLOWLOCATION и ограничить количество переходов через CURLOPT_MAXREDIRS.


$ch = curl_init('http://bit.ly/short');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
$response = curl_exec($ch);
$finalUrl = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
curl_close($ch);
echo $finalUrl;

Бесконечный редирект или слишком много переходов

Ограничение CURLOPT_MAXREDIRS помогает избежать зацикливания. Если сайт использует редиректы с куками, необходимо также обрабатывать cookie (см. следующий вариант).

Как сохранить и отправить cookie при повторных запросах?

Для работы с сессиями используются опции CURLOPT_COOKIEJAR (файл для записи cookie) и CURLOPT_COOKIEFILE (файл для чтения cookie).


$ch = curl_init('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');
// выполнение первого запроса (логин)
$result = curl_exec($ch);
// теперь куки сохранены, можно делать второй запрос тем же handle
curl_setopt($ch, CURLOPT_URL, 'https://example.com/dashboard');
$result2 = curl_exec($ch);
curl_close($ch);

Можно также задать строку кук напрямую через CURLOPT_COOKIE.

Как отправить файл через cURL?

Для загрузки файлов используется класс CURLFile (доступен с PHP 5.5). Файл передаётся в CURLOPT_POSTFIELDS как элемент массива с ключом - именем поля.


$file = new CURLFile('/path/to/file.pdf', 'application/pdf', 'document.pdf');
$data = ['upload' => $file];
$ch = curl_init('https://example.com/upload');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);

Ошибка при загрузке: файл не найден или превышен лимит post_max_size

Убедитесь, что файл существует, и проверьте настройки PHP (upload_max_filesize, post_max_size).

Как выполнить несколько запросов параллельно?

cURL поддерживает мульти-обработчики (curl_multi_init), позволяющие запускать запросы асинхронно. Это ускоряет работу, если нужно обойти несколько URL.


$urls = ['http://example.com', 'http://example.org', 'http://example.net'];
$mh = curl_multi_init();
$handles = [];
foreach ($urls as $i => $url) {
    $handles[$i] = curl_init($url);
    curl_setopt($handles[$i], CURLOPT_RETURNTRANSFER, true);
    curl_multi_add_handle($mh, $handles[$i]);
}
$running = null;
do {
    curl_multi_exec($mh, $running);
    curl_multi_select($mh);
} while ($running > 0);
$results = [];
foreach ($handles as $i => $ch) {
    $results[$i] = curl_multi_getcontent($ch);
    curl_multi_remove_handle($mh, $ch);
    curl_close($ch);
}
curl_multi_close($mh);
// $results содержит ответы

Расширенная конфигурация с curl_setopt_array

Для удобства можно передать массив опций одной функцией curl_setopt_array. Это уменьшает количество строк кода и улучшает читаемость.


$options = [
    CURLOPT_URL            => 'https://api.example.com',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 30,
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    CURLOPT_POST           => true,
    CURLOPT_POSTFIELDS     => json_encode(['key' => 'value']),
];
$ch = curl_init();
curl_setopt_array($ch, $options);
$response = curl_exec($ch);
curl_close($ch);

Такой подход удобен при многократном использовании одного набора опций.

Продвинутые примеры использования cURL в PHP

Пример 1: Запрос с базовой аутентификацией (HTTP Basic)

Для доступа к ресурсам, защищённым базовой аутентификацией, используется опция CURLOPT_USERPWD. Пример:

Пример

$ch = curl_init('https://api.example.com/private');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERPWD, 'username:password');
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo "HTTP код: " . $httpCode . "\n";
echo $response;
HTTP код: 200
{"status":"success","data":...}

Если сервер использует дайджест-аутентификацию, применяется CURLOPT_HTTPAUTH с CURLAUTH_DIGEST.

Пример 2: Отправка JSON через POST

Многие современные API ожидают JSON. Необходимо правильно задать Content-Type и сериализовать данные.

Пример

$data = ['title' => 'Example', 'body' => 'Content', 'userId' => 1];
$json = json_encode($data);
$ch = curl_init('https://jsonplaceholder.typicode.com/posts');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_POSTFIELDS     => $json,
    CURLOPT_HTTPHEADER     => [
        'Content-Type: application/json',
        'Content-Length: ' . strlen($json)
    ]
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo "Code: $httpCode\n";
echo $response;
Code: 201
{
  "title": "Example",
  "body": "Content",
  "userId": 1,
  "id": 101
}

Пример 3: Работа с SSL через сертификат CA

Для безопасных HTTPS запросов рекомендуется использовать проверку SSL. Если у вас есть файл CA-сертификата (например, cacert.pem из curl), его путь указывается в CURLOPT_CAINFO.

Пример

$ch = curl_init('https://secure.example.com');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_SSL_VERIFYPEER => true,
    CURLOPT_CAINFO         => '/path/to/cacert.pem',
    CURLOPT_SSL_VERIFYHOST => 2
]);
$response = curl_exec($ch);
if ($response === false) {
    echo "Ошибка SSL: " . curl_error($ch);
}
curl_close($ch);

Если проверка отключена (CURLOPT_SSL_VERIFYPEER = false), снижается безопасность соединения.

Пример 4: Загрузка файла с прогрессом

С помощью CURLOPT_PROGRESSFUNCTION можно отслеживать прогресс загрузки (download) или отправки (upload). Функция обратного вызова получает аргументы с размерами.

Пример

function progressCallback($resource, $download_size, $downloaded, $upload_size, $uploaded) {
    if ($download_size > 0) {
        $percent = round($downloaded / $download_size * 100);
        echo "Загружено: $percent%\n";
    }
}

$ch = curl_init('https://example.com/largefile.zip');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_PROGRESSFUNCTION => 'progressCallback',
    CURLOPT_NOPROGRESS       => false   // отключаем встроенный прогресс
]);
$data = curl_exec($ch);
curl_close($ch);

Результат - строка из вызовов коллбэка в консоли. Важно: CURLOPT_NOPROGRESS должен быть false.

Пример 5: Использование cURL с proxy (HTTP/HTTPS)

Для работы через прокси-сервер устанавливаются опции CURLOPT_PROXY, CURLOPT_PROXYPORT и, если требуется аутентификация, CURLOPT_PROXYUSERPWD.

Пример

$ch = curl_init('http://httpbin.org/ip');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_PROXY          => '192.168.1.100',
    CURLOPT_PROXYPORT      => 3128,
    CURLOPT_PROXYUSERPWD   => 'user:pass'
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
  "origin": "192.168.1.100"
}

Тип прокси можно задать через CURLOPT_PROXYTYPE (например, CURLPROXY_SOCKS5).

Пример 6: Получение информации о запросе (curl_getinfo)

После выполнения запроса можно извлечь метаданные: HTTP код, размер, время выполнения, эффективный URL и др.

Пример

$ch = curl_init('https://www.example.com');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$body = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
echo "HTTP code: " . $info['http_code'] . "\n";
echo "Content type: " . $info['content_type'] . "\n";
echo "Total time: " . $info['total_time'] . " сек\n";
echo "Effective URL: " . $info['url'] . "\n";
HTTP code: 200
Content type: text/html; charset=UTF-8
Total time: 0.234 сек
Effective URL: https://www.example.com/

Пример 7: Запрос с пользовательским методом (DELETE, PUT, PATCH)

Опция CURLOPT_CUSTOMREQUEST позволяет задать любой HTTP метод. Например, DELETE запрос с телом (некоторые API требуют тело и при удалении).

Пример

$data = ['reason' => 'test'];
$json = json_encode($data);
$ch = curl_init('https://api.example.com/resource/123');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'DELETE',
    CURLOPT_POSTFIELDS     => $json,
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json']
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo "HTTP $httpCode: $response";

Пример 8: Использование cURL через file_get_contents с контекстом (альтернативный подход)

Хотя это не cURL, иногда упоминается как альтернатива. Создание потока с помощью stream_context_create и выполнение GET запроса:

Пример

$opts = [
    'http' => [
        'method' => 'GET',
        'header' => "User-Agent: MyAgent/1.0\r\n"
    ]
];
$context = stream_context_create($opts);
$result = file_get_contents('http://example.com', false, $context);
if ($result === false) {
    echo "Ошибка получения данных";
} else {
    echo $result;
}

Недостатки: нет поддержки параллельных запросов, менее гибкая обработка ошибок, ограниченные возможности настройки SSL.

Пример 9: Закрытие и повторное использование handle

Handle можно переиспользовать для нескольких последовательных запросов, меняя только URL или другие опции. Это экономит ресурсы.

Пример

$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

// Первый запрос
curl_setopt($ch, CURLOPT_URL, 'http://api1.example.com');
$result1 = curl_exec($ch);

// Второй запрос (сброс некоторых опций не обязателен)
curl_setopt($ch, CURLOPT_URL, 'http://api2.example.com');
$result2 = curl_exec($ch);

curl_close($ch);

Важно: при смене URL cURL может сбрасывать некоторые внутренние состояния (например, cookie), но общие опции (таймауты, заголовки) сохраняются.

Пример 10: Обработка chunked transfer encoding

cURL автоматически декодирует chunked ответы, если включена опция CURLOPT_ENCODING с пустой строкой или 'gzip,deflate'. Пример сжатого ответа:

Пример

$ch = curl_init('http://httpbin.org/gzip');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING       => 'gzip,deflate'
]);
$response = curl_exec($ch);
curl_close($ch);
var_dump(json_decode($response, true));
array(3) {
  ["gzipped"] => bool(true)
  ["headers"] => array(...)
  ["method"] => string(3) "GET"
}

Без указания CURLOPT_ENCODING cURL не будет обрабатывать сжатие и вернёт бинарные данные.

- Php curl content (содержимое ответа php curl)
- Php curl html (php curl html)
- Php curl error (ошибки php curl)
- Php curl https (php curl https)
- Php curl get (php curl get запрос)
- Php curl init (php curl init)

PHP cURL init - comments

En
Php curl init (php)