Я уже давно использую принятый код ответа (код Фелипе), и он отлично работает (спасибо, Фелипе!).
Однако недавно я обнаружил, что у него есть проблемы с пустыми объектами или массивами. Например, при отправке этого объекта:
{
A: 1,
B: {
a: [ ],
},
C: [ ],
D: "2"
}
PHP, кажется, не видит B и C вообще. Это получает это:
[
"A" => "1",
"B" => "2"
]
Посмотрите на фактический запрос в Chrome показывает это:
A: 1
:
D: 2
Я написал альтернативный фрагмент кода. Кажется, это хорошо работает с моими вариантами использования, но я не тестировал это широко, поэтому используйте с осторожностью.
Я использовал TypeScript, потому что мне нравится строгая типизация, но было бы легко преобразовать его в чистый JS:
angular.module("MyModule").config([ "$httpProvider", function($httpProvider: ng.IHttpProvider) {
// Use x-www-form-urlencoded Content-Type
$httpProvider.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded;charset=utf-8";
function phpize(obj: Object | any[], depth: number = 1): string[] {
var arr: string[] = [ ];
angular.forEach(obj, (value: any, key: string) => {
if (angular.isObject(value) || angular.isArray(value)) {
var arrInner: string[] = phpize(value, depth + 1);
var tmpKey: string;
var encodedKey = encodeURIComponent(key);
if (depth == 1) tmpKey = encodedKey;
else tmpKey = `[${encodedKey}]`;
if (arrInner.length == 0) {
arr.push(`${tmpKey}=`);
}
else {
arr = arr.concat(arrInner.map(inner => `${tmpKey}${inner}`));
}
}
else {
var encodedKey = encodeURIComponent(key);
var encodedValue;
if (angular.isUndefined(value) || value === null) encodedValue = "";
else encodedValue = encodeURIComponent(value);
if (depth == 1) {
arr.push(`${encodedKey}=${encodedValue}`);
}
else {
arr.push(`[${encodedKey}]=${encodedValue}`);
}
}
});
return arr;
}
// Override $http service's default transformRequest
(<any>$httpProvider.defaults).transformRequest = [ function(data: any) {
if (!angular.isObject(data) || data.toString() == "[object File]") return data;
return phpize(data).join("&");
} ];
} ]);
Он менее эффективен, чем код Фелипе, но я не думаю, что это имеет большое значение, поскольку он должен быть немедленным по сравнению с общими издержками самого HTTP-запроса.
Теперь PHP показывает:
[
"A" => "1",
"B" => [
"a" => ""
],
"C" => "",
"D" => "2"
]
Насколько я знаю, PHP не может распознать, что Ba и C - пустые массивы, но, по крайней мере, появляются ключи, что важно, когда есть код, который опирается на определенную структуру, даже если он по существу пуст внутри.
Также обратите внимание, что он преобразует неопределенные s и нулевые s в пустые строки.