Обработка JSON из внешних источников в PHP

Раздел: Веб-программирование -> Обработка HTTP-запросов

Способы получения JSON в PHP

Как эффективно получить JSON с помощью cURL?

cURL (Client URL Library) считается наиболее гибким и надёжным решением, особенно при работе с внешними API. Он поддерживает HTTPS, прокси, заголовки, таймауты и POST-запросы.


<?php
$ch = curl_init('https://api.example.com/data.json');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Accept: application/json']);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($httpCode !== 200) {
    // обработка ошибки HTTP
}
$data = json_decode($response, true);
?>
  

Php получить куки (получение куки в php)

Пояснение:

  • curl_init - инициализация сеанса cURL.
  • CURLOPT_RETURNTRANSFER - возвращает ответ в виде строки вместо вывода на экран.
  • curl_exec - выполняет запрос.
  • curl_getinfo - получает HTTP-код ответа.
  • json_decode - преобразует JSON в массив (true) или объект (false).

Типичные проблемы:

  • Отсутствие расширения php-curl - проверьте наличие extension=curl в php.ini.
  • Ошибки SSL - используйте curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false) для тестового окружения (не для продакшна).
  • Таймауты - задайте CURLOPT_TIMEOUT и CURLOPT_CONNECTTIMEOUT.

Цель: получение данных с удалённого REST API с полным контролем над запросом.

Как получить JSON с помощью file_get_contents?

Встроенная функция file_get_contents с контекстом потока подходит для простых GET-запросов без дополнительных заголовков и авторизации.


<?php
$options = [
    'http' => [
        'method' => 'GET',
        'header' => "Accept: application/json\r\n"
    ]
];
$context = stream_context_create($options);
$response = file_get_contents('https://api.example.com/data.json', false, $context);
if ($response === false) {
    // ошибка получения
}
$data = json_decode($response, true);
?>
  

Php получить html (получение html-кода в php)

Пояснение:

  • stream_context_create - создаёт контекст с HTTP-параметрами.
  • file_get_contents - читает содержимое URL, используя контекст.
  • Метод не требует дополнительного расширения, но сложнее настраивать POST-запросы и SSL.

Типичные проблемы:

  • allow_url_fopen должен быть включён в php.ini.
  • Отсутствие обработки редиректов - по умолчанию редиректы не обрабатываются.
  • Сложности с POST-запросами и передачей тела.

Цель: быстрое получение JSON без установки дополнительных библиотек.

Как получить JSON с помощью Guzzle?

Guzzle - популярная библиотека PSR-7 для HTTP-запросов. Она абстрагирует детали cURL и позволяет писать чистый код.


<?php
require 'vendor/autoload.php';

use GuzzleHttp\Client;

$client = new Client(['base_uri' => 'https://api.example.com']);
try {
    $response = $client->request('GET', '/data.json', [
        'headers' => ['Accept' => 'application/json']
    ]);
    $body = $response->getBody()->getContents();
    $data = json_decode($body, true);
} catch (Exception $e) {
    // обработка исключения
}
?>
  

Php получить заголовок (получение заголовка в php)

Пояснение:

  • Требуется установка через Composer: composer require guzzlehttp/guzzle.
  • Client - основной класс для отправки запросов.
  • request - возвращает объект Response, из которого извлекается тело.
  • Исключения обрабатывают ошибки HTTP (4xx, 5xx) и таймауты.

Типичные проблемы:

  • Необходимость установки Composer и подключения автозагрузки.
  • Потребление памяти для крупных ответов - используйте потоковое чтение.
  • Конфликт версий расширения cURL.

Цель: создание современного HTTP-клиента с поддержкой middleware и асинхронных запросов.

Как получить JSON с помощью stream_context_create без file_get_contents?

Можно использовать fopen с контекстом для потокового чтения.


<?php
$context = stream_context_create([
    'http' => ['method' => 'GET']
]);
$stream = fopen('https://api.example.com/data.json', 'r', false, $context);
if ($stream) {
    $response = stream_get_contents($stream);
    fclose($stream);
    $data = json_decode($response, true);
}
?>
  

Пояснение: Подходит для больших файлов, когда нужно обрабатывать данные по частям. Однако при HTTP-запросах редко используется.

- Php получить параметры (получение параметров запроса в php)
- Php получить переменные (получение переменных запроса в php)
- получить ссылку php (получение ссылки в php)

Расширенные примеры получения JSON

Пример 1. Отправка POST-запроса с JSON-телом через cURL

Пример

<?php
$postData = ['name' => 'Иван', 'age' => 30];
$jsonPayload = json_encode($postData);

$ch = curl_init('https://api.example.com/users');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $jsonPayload,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'Content-Length: ' . strlen($jsonPayload)
    ],
    CURLOPT_TIMEOUT => 10,
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($httpCode === 201) {
    $result = json_decode($response, true);
    print_r($result);
} else {
    echo "Ошибка: HTTP $httpCode";
}
?>
Array
(
    [id] => 123
    [name] => Иван
    [age] => 30
)

Пояснение:

  • JSON-данные передаются в теле POST-запроса.
  • Установлен заголовок Content-Type: application/json.
  • Код 201 означает успешное создание ресурса.
  • Таймаут 10 секунд предотвращает зависание.

Частая ошибка:

Отсутствие заголовка Content-Length может привести к зависанию сервера. В современных версиях PHP cURL вычисляет его автоматически, но для совместимости лучше указывать.

Пример 2. Аутентификация через Bearer token (cURL)

Пример

<?php
$token = 'your_access_token';
$ch = curl_init('https://api.example.com/secure/data');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . $token,
        'Accept: application/json'
    ],
    CURLOPT_SSL_VERIFYPEER => true, // в продакшне обязательно
]);
$response = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'cURL error: ' . curl_error($ch);
} else {
    $data = json_decode($response, true);
}
curl_close($ch);
?>
Array
(
    [status] => success
    [data] => [...]
)

Пояснение:

  • Заголовок Authorization передаёт токен.
  • CURLOPT_SSL_VERIFYPEER включён для проверки сертификата.
  • Проверка curl_errno выявляет транспортные ошибки.

Пример 3. Получение JSON с обработкой ошибок парсинга

Пример

<?php
$response = file_get_contents('https://api.example.com/possibly-broken');
if ($response === false) {
    die('Не удалось получить данные');
}
$data = json_decode($response, true);
if (json_last_error() !== JSON_ERROR_NONE) {
    echo 'Ошибка JSON: ' . json_last_error_msg();
} else {
    print_r($data);
}
?>
Ошибка JSON: Syntax error, malformed JSON

Пояснение:

Функция json_last_error возвращает код ошибки, json_last_error_msg - текстовое описание. Это позволяет корректно обработать повреждённый JSON.

Пример 4. Получение JSON с помощью Guzzle и обработка исключений

Пример

<?php
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\ClientException;

$client = new Client(['timeout' => 5.0]);
try {
    $response = $client->get('https://api.example.com/data', [
        'headers' => ['X-Api-Key' => '12345']
    ]);
    $body = (string) $response->getBody();
    $data = json_decode($body, true);
} catch (ClientException $e) {
    // 4xx ошибки
    echo 'HTTP ошибка: ' . $e->getCode();
} catch (ConnectException $e) {
    // проблемы сети
    echo 'Сетевая ошибка: ' . $e->getMessage();
} catch (Exception $e) {
    // прочие ошибки
    echo 'Ошибка: ' . $e->getMessage();
}
?>
HTTP ошибка: 401

Пояснение:

  • Guzzle выбрасывает специфичные исключения для разных типов ошибок.
  • Таймаут задаётся в конструкторе Client.
  • Заголовки передаются массивом в опциях запроса.

Пример 5. Потоковая загрузка большого JSON файла с помощью stream_context и fopen

Пример

<?php
$context = stream_context_create([
    'http' => [
        'method' => 'GET',
        'header' => "Accept: application/json\r\n"
    ]
]);
$stream = fopen('https://api.example.com/bigdata.json', 'r', false, $context);
if ($stream) {
    $chunkSize = 8192;
    $result = '';
    while (!feof($stream)) {
        $result .= fread($stream, $chunkSize);
    }
    fclose($stream);
    $data = json_decode($result, true);
    if ($data === null) {
        echo 'Невалидный JSON';
    } else {
        echo 'Загружено ' . count($data) . ' записей';
    }
}
?>
Загружено 15000 записей

Пояснение:

Для очень больших JSON лучше использовать потоковый парсер (например, JsonStreamingParser), но данный пример показывает базовое чтение блоками.

Пример 6. Использование file_get_contents с обработкой редиректов

Пример

<?php
$options = [
    'http' => [
        'method' => 'GET',
        'follow_location' => 1, // разрешить редиректы
        'max_redirects' => 5,
    ],
    'ssl' => [
        'verify_peer' => false, // только для тестов
    ]
];
$context = stream_context_create($options);
$response = @file_get_contents('https://short.url/to/json', false, $context);
if ($response === false) {
    $error = error_get_last();
    echo 'Ошибка: ' . $error['message'];
} else {
    $data = json_decode($response, true);
}
?>
Array
(
    [redirected] => true
    [data] => ...
)

Пояснение:

Параметр follow_location включает автоматическое следование за редиректами. max_redirects ограничивает количество переходов.

Получение JSON в PHP - comments

En
Php получить json (php)