Как правильно вернуть JSON из PHP скрипта и почему у меня ничего не работает?
Правильный способ возврата JSON из PHP
Проблема в том, что вы вызываете json_encode() и просто выводите результат через echo. Этого недостаточно для корректной работы с JSON. Давайте разберем все шаги по порядку.
1. Установка правильного заголовка Content-Type
HTTP-заголовок Content-Type сообщает клиенту (браузеру, curl, JavaScript), в каком формате сервер отправляет данные. Для JSON используется MIME-тип application/json. Если этого не сделать, клиент может интерпретировать ответ как обычный текст или HTML.
<?php
$data = [
"name" => "Иван",
"age" => 25,
"city" => "Москва"
];
header('Content-Type: application/json; charset=utf-8');
echo json_encode($data);
?>
2. Запрет на случайный вывод до JSON
Очень частая ошибка — пробелы, пустые строки или лишние символы до открывающего тега <?php или после закрывающего ?>. Любой символ, попавший в вывод до вызова json_encode(), сделает JSON невалидным.
Плохо:
[пробел]
<?php
echo json_encode($data);
?>
[пустая строка]
Хорошо:
<?php
header('Content-Type: application/json');
echo json_encode($data);
?>
Лучше вообще не ставить закрывающий тег ?> в файлах, которые содержат только PHP-код — это предотвратит случайный вывод пробелов.
3. Обработка ошибок и кодировка
Функция json_encode() может вернуть false, если данные содержат некорректные символы (например, не-UTF-8). Всегда проверяйте результат!
<?php
header('Content-Type: application/json; charset=utf-8');
$data = [
"name" => "Иван",
"age" => 25,
"message" => "Привет, мир!"
];
$json = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
if ($json === false) {
// Обработка ошибки
http_response_code(500);
echo json_encode(["error" => "Ошибка кодирования JSON: " . json_last_error_msg()]);
exit;
}
echo $json;
?>
Флаг JSON_UNESCAPED_UNICODE сохраняет русские буквы как есть (вместо \uXXXX), а JSON_UNESCAPED_SLASHES не экранирует слеши.
4. Полный рабочий пример
<?php
// 1. Устанавливаем заголовок
header('Content-Type: application/json; charset=utf-8');
// 2. Данные для отправки
$response = [
"status" => "success",
"data" => [
"id" => 1,
"name" => "Иван",
"age" => 25,
"skills" => ["PHP", "JavaScript", "Python"]
],
"timestamp" => time()
];
// 3. Кодируем с проверкой
$json = json_encode($response, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
if ($json === false) {
http_response_code(500);
echo json_encode(["error" => "Internal server error"]);
exit;
}
// 4. Отдаем результат
echo $json;
?>
5. Проверка через curl
После правильной настройки ваш скрипт можно протестировать в терминале:
curl -i http://your-site.com/api.php
Вы должны увидеть заголовок Content-Type: application/json и корректный JSON в теле ответа.
Ключевые моменты:
- Всегда устанавливайте заголовок
Content-Type: application/jsonперед выводом данных. - Убедитесь, что в файле нет лишних символов до
<?phpи после?>. - Используйте флаги
JSON_UNESCAPED_UNICODEиJSON_UNESCAPED_SLASHESдля корректной работы с кириллицей. - Проверяйте результат
json_encode()наfalse. - Не используйте закрывающий тег
?>в файлах с чистым PHP-кодом.
Альтернативный подход: использование PHP-фреймворков
Если вы работаете над серьезным проектом или API, рекомендую использовать готовые решения, например, микрофреймворк Slim или полновесный Laravel. Они автоматически управляют заголовками, кодировкой и обработкой ошибок.
Пример с использованием Slim 4:
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/{id}', function (Request $request, Response $response, array $args) {
$data = [
"id" => (int)$args['id'],
"name" => "Иван",
"age" => 25
];
$payload = json_encode($data, JSON_UNESCAPED_UNICODE);
$response->getBody()->write($payload);
return $response
->withHeader('Content-Type', 'application/json')
->withStatus(200);
});
$app->run();
Преимущества такого подхода:
- Автоматическая обработка заголовков и статусов HTTP
- Встроенная поддержка CORS, middleware, роутинга
- Защита от типичных ошибок (случайный вывод, пробелы)
- Удобное тестирование и документация
Если вы только начинаете — сначала освойте чистый PHP, но для продакшена всегда используйте фреймворки. Это сэкономит часы отладки и сделает код профессиональным.