He estado usando el código de respuesta aceptado (código de Felipe) por un tiempo y ha estado funcionando muy bien (¡gracias, Felipe!).
Sin embargo, recientemente descubrí que tiene problemas con objetos vacíos o matrices. Por ejemplo, al enviar este objeto:
{
A: 1,
B: {
a: [ ],
},
C: [ ],
D: "2"
}
PHP no parece ver B y C en absoluto. Se pone esto:
[
"A" => "1",
"B" => "2"
]
Un vistazo a la solicitud real en Chrome muestra esto:
A: 1
:
D: 2
Escribí un fragmento de código alternativo. Parece funcionar bien con mis casos de uso, pero no lo he probado exhaustivamente, así que úselo con precaución.
Usé TypeScript porque me gusta la escritura fuerte pero sería fácil convertir a JS puro:
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("&");
} ];
} ]);
Es menos eficiente que el código de Felipe, pero no creo que importe mucho, ya que debería ser inmediato en comparación con la sobrecarga general de la solicitud HTTP.
Ahora PHP muestra:
[
"A" => "1",
"B" => [
"a" => ""
],
"C" => "",
"D" => "2"
]
Hasta donde sé, no es posible hacer que PHP reconozca que Ba y C son matrices vacías, pero al menos aparecen las claves, lo cual es importante cuando hay código que se basa en una determinada estructura, incluso cuando está esencialmente vacío por dentro.
También tenga en cuenta que convierte s indefinidos y nulos en cadenas vacías.