Как правильно вернуть JSON из PHP-скрипта?
Правильная отправка JSON из PHP
Ваша проблема типична для начинающих разработчиков. Главная причина, почему JSON может не работать — это лишний вывод перед или после самого JSON. Давайте разберем правильный подход.
Базовое решение
Вот минимально правильный способ вернуть JSON:
<?php
// 1. Устанавливаем заголовок Content-Type
header('Content-Type: application/json; charset=utf-8');
// 2. Формируем данные
$data = [
'status' => 'success',
'message' => 'Данные получены',
'user' => [
'name' => 'Иван',
'age' => 30,
'hobbies' => ['программирование', 'чтение']
]
];
// 3. Преобразуем в JSON и выводим
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
// 4. Завершаем скрипт
exit;
?>
Почему это важно?
- header() — сообщает клиенту, что ответ — это JSON. Без этого браузер может интерпретировать ответ как HTML.
- JSON_UNESCAPED_UNICODE — сохраняет русские буквы (иначе они будут в виде \u0438\u0432\u0430\u043d).
- JSON_PRETTY_PRINT — делает JSON читаемым (для продакшена обычно убирают, чтобы уменьшить размер).
- exit — гарантирует, что после вывода JSON не будет никакого лишнего кода.
Обработка ошибок
Чтобы избежать "мусора" от PHP-предупреждений, используйте следующий подход:
<?php
// Включаем отображение ошибок только для разработки
// В продакшене ошибки должны быть скрыты
ini_set('display_errors', 0);
error_reporting(E_ALL);
// Перехватываем все ошибки через буферизацию
ob_start();
// Ваш код
try {
$data = ['result' => 'ok'];
echo json_encode($data, JSON_THROW_ON_ERROR);
// Очищаем буфер и выводим только JSON
ob_end_flush();
} catch (Exception $e) {
// Очищаем буфер и выводим ошибку в JSON
ob_end_clean();
echo json_encode([
'status' => 'error',
'message' => $e->getMessage()
]);
}
exit;
?>
Продвинутый вариант с классом
<?php
class JsonResponse {
public static function send($data, int $statusCode = 200) {
http_response_code($statusCode);
header('Content-Type: application/json; charset=utf-8');
$json = json_encode($data, JSON_UNESCAPED_UNICODE);
if ($json === false) {
// Ошибка кодирования JSON
http_response_code(500);
echo json_encode([
'status' => 'error',
'message' => 'Ошибка формирования JSON: ' . json_last_error_msg()
]);
} else {
echo $json;
}
exit;
}
}
// Использование
$response = [
'users' => [
['id' => 1, 'name' => 'Анна'],
['id' => 2, 'name' => 'Петр']
]
];
JsonResponse::send($response, 200);
?>
Распространенные ошибки и их решения
- Пробел или пустая строка перед <?php — убедитесь, что в файле нет ничего до открывающего тега PHP.
- BOM-маркер в UTF-8 — сохраняйте файлы без BOM (UTF-8 without BOM).
- Вывод после echo json_encode — используйте exit или return.
- Неверный Content-Type — всегда явно задавайте header('Content-Type: application/json').
Теперь ваш JavaScript сможет успешно парсить ответ:
fetch('/api/user.php')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Ошибка:', error));
<<Альтернативный подход: использование фреймворков и библиотек
Если вы не хотите писать обработку JSON вручную, рекомендую использовать готовые решения. Например, микрофреймворк Slim 4 или Laravel предоставляют удобные методы для работы с JSON-ответами.
Пример с Slim 4
<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
require __DIR__ . '/vendor/autoload.php';
$app = AppFactory::create();
$app->get('/api/user', function (Request $request, Response $response) {
$data = ['name' => 'Иван', 'age' => 30];
// Преобразуем в JSON и возвращаем
$response->getBody()->write(json_encode($data, JSON_UNESCAPED_UNICODE));
return $response->withHeader('Content-Type', 'application/json');
});
$app->run();
?>
Пример с Laravel
<?php
// В контроллере
public function getUser() {
$data = ['name' => 'Иван', 'age' => 30];
return response()->json($data);
}
Преимущества использования фреймворков:
- Автоматическая обработка заголовков и кодировки.
- Встроенная обработка ошибок и исключений.
- Поддержка CORS (если нужно).
- Удобное тестирование.
Недостатки:
- Требуется установка и настройка фреймворка.
- Избыточно для простых скриптов.
Если ваш проект небольшой, используйте первый вариант. Если планируете развивать API — лучше сразу взять фреймворк.