Правильная обработка

Один из современных способов взаимодействия фронтенда с бэкендом — это обмен данными в формате JSON. И, как показывает практика, не каждый может рассказать как же можно наладить такую взаимосвязь, обработать данные и в чем разница между следующими вариантами запросов.

Один из современных типичных способов передачи JSON с фронтенда на бэкенд выглядит так:

var data = {foo: {bar: [1,2,3]}};

fetch('backend.php', {
method : 'POST',
cache : 'no-cache',
headers: {'Content-Type':'application/json'},
body : JSON.stringify(data)
})
.then(res=>res.json())
.then(console.log)
;

Другой способ:

var body = new FormData;
body.append('foo', 123);
body.append('bar', [1,2,3]);
body.append('buz', 'abc');

fetch('backend.php', {
method: 'POST',
cache : 'no-cache',
body
})
.then(res=>res.json())
.then(console.log)
;

Чем отличаются эти два варианта? Как правильно обработать данные на сервере?

FORM URLENCODED

Начнем со второго примера. Отличительная черта этого варианта отправки запроса это формат, который определяется заголовком:

application/x-www-form-urlencoded

По идее его можно было бы указать явно:

fetch('backend.php', {
...
headers: {'Content-Type':'application/x-www-form-urlencoded'},
...
})

Этот формат многим знаком, так как по сути это формат отправки данных из HTML форм. В этом формате значения кодируются парами ключ-значение, разделенных символом '&', и с '=' между ключом и значением. Все значения передаются в виде строки и это важно! При попытке передать массив или объект, они будут представлены в виде строки. И бремя по кодированию этих объектов ложится на плечи фронтендера и бекендера, которые будут обратно приводить все к нужным типам.

На сервере получить такой формат очень просто, достаточно обратиться к встроенным глобальным перменным $_POST и $_REQUEST:

$_POST['foo'] // string("123")
$_POST['bar'] // string("1,2,3")
$_POST['buz'] // string("abc")

А чем же отличается принципиально первый запрос от второго?

В первую очередь тем, что вы не сможете их увидеть в привычных глобальных переменных $_REQUEST и $_POST. Они там не хранятся и их нужно получать другим способом. Вопрос жизненный и даже встречающийся на собеседованиях.

JSON Request

Если вы работаете с Node.js бэкендом, то там для обработки таких запросов по сути ничего специального не нужно. Вы по сути обращаетесь к объекту body из запроса. А вот в PHP эти данные автоматом не кладутся в супер глобальные переменные. Но есть способ получить такие данные.

До версии PHP 5.6 в языке была супер глобальная переменная $HTTP_RAW_POST_DATA , но с версии 7.0 она была удалена. И теперь для чтения сырых данных мы должны обратиться к входному потоку:

php://input

Это не сложно, просто нужно про это знать. Чтобы обработать JSON пишем такой код:

if ('application/json' == $_SERVER['CONTENT_TYPE']
&& 'POST' == $_SERVER['REQUEST_METHOD'])
{
$json = json_decode(file_get_contents('php://input'), true);
}

Для того, чтобы соблюдать некоторый канон, я использую слово JSON и добавляю все это в $_REQUEST и $_POST:

if ('application/json' == $_SERVER['CONTENT_TYPE']
&& 'POST' == $_SERVER['REQUEST_METHOD'])
{
$_REQUEST['JSON'] = json_decode(
file_get_contents('php://input'), true
);
$_POST['JSON'] = & $_REQUEST['JSON'];
}

Вот вроде бы и все. Простая тема, но порой даже такие простые вещи вызывают вопросы.