Обработка JSON из внешних источников в PHP
Способы получения 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-запросах редко используется.
Расширенные примеры получения 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 ограничивает количество переходов.