有人能告诉我为什么下面的语句没有将post数据发送到指定的url吗?url被调用,但在服务器上,当我打印$_POST -我得到一个空数组。如果我在控制台中打印消息,然后将其添加到数据-它显示了正确的内容。
$http.post('request-url', { 'message' : message });
我也尝试过将数据作为字符串(具有相同的结果):
$http.post('request-url', "message=" + message);
当我以以下格式使用它时,它似乎正在工作:
$http({
method: 'POST',
url: 'request-url',
data: "message=" + message,
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
});
但是是否有一种方法可以用$http.post() -我总是必须包括头以便它工作吗?我相信上面的内容类型是指定发送数据的格式,但我可以把它作为javascript对象发送吗?
我一直在使用公认的答案的代码(Felipe的代码)一段时间,它工作得很好(谢谢,Felipe!)。
但是,最近我发现它有空对象或数组的问题。
例如,当提交这个对象时:
{
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("&");
} ];
} ]);
它的效率比Felipe的代码低,但我认为这无关紧要,因为与HTTP请求本身的整体开销相比,它应该是即时的。
现在PHP显示:
[
"A" => "1",
"B" => [
"a" => ""
],
"C" => "",
"D" => "2"
]
据我所知,让PHP识别B.a和C是空数组是不可能的,但至少键会出现,当代码依赖于某个结构时,这很重要,即使它内部实际上是空的。
还要注意,它将未定义的和null转换为空字符串。
我知道已经接受了答案。但是,如果这个答案因为任何原因不适合他们,下面的内容可能会对未来的读者有所帮助。
Angular不会像jQuery那样使用ajax。当我尝试按照指南修改angular $httpprovider时,我遇到了其他问题。例如,我使用codeigniter,其中$this->input->is_ajax_request()函数总是失败(这是由另一个程序员编写的,并在全局使用,所以不能改变)说这不是真正的ajax请求。
为了解决这个问题,我接受了延期承诺的帮助。我在Firefox和ie9上进行了测试,效果很好。
我在angular代码的外部定义了以下函数。这个函数使常规jquery ajax调用和返回延迟/承诺(我仍在学习)对象。
function getjQueryAjax(url, obj){
return $.ajax({
type: 'post',
url: url,
cache: true,
data: obj
});
}
然后我用下面的代码称它为角代码。请注意,我们必须使用$scope.$apply()手动更新$scope。
var data = {
media: "video",
scope: "movies"
};
var rPromise = getjQueryAjax("myController/getMeTypes" , data);
rPromise.success(function(response){
console.log(response);
$scope.$apply(function(){
$scope.testData = JSON.parse(response);
console.log($scope.testData);
});
}).error(function(){
console.log("AJAX failed!");
});
这可能不是完美的答案,但它允许我在angular中使用jquery ajax调用,并允许我更新$scope。
我在使用asp.net MVC时遇到了同样的问题,在这里找到了解决方案
刚接触AngularJS的人有很多困惑,为什么
$http服务简写函数($http.post()等)不会出现
可切换与jQuery的等价物(jQuery.post()等)
不同之处在于jQuery和AngularJS如何序列化和传输数据。从根本上说,问题在于你所选择的服务器语言无法理解AngularJS的传输…jQuery默认使用
Content-Type: x-www-form-urlencoded
以及熟悉的foo=bar&baz=moe序列化。
AngularJS使用
Content-Type: application/json
{"foo": "bar", "baz": "moe"}
JSON序列化,不幸的是一些Web服务器语言—特别是
php—不要本地反序列化。
效果非常好。
CODE
// Your app's root module...
angular.module('MyModule', [], function($httpProvider) {
// Use x-www-form-urlencoded Content-Type
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';
/**
* The workhorse; converts an object to x-www-form-urlencoded serialization.
* @param {Object} obj
* @return {String}
*/
var param = function(obj) {
var query = '', name, value, fullSubName, subName, subValue, innerObj, i;
for(name in obj) {
value = obj[name];
if(value instanceof Array) {
for(i=0; i<value.length; ++i) {
subValue = value[i];
fullSubName = name + '[' + i + ']';
innerObj = {};
innerObj[fullSubName] = subValue;
query += param(innerObj) + '&';
}
}
else if(value instanceof Object) {
for(subName in value) {
subValue = value[subName];
fullSubName = name + '[' + subName + ']';
innerObj = {};
innerObj[fullSubName] = subValue;
query += param(innerObj) + '&';
}
}
else if(value !== undefined && value !== null)
query += encodeURIComponent(name) + '=' + encodeURIComponent(value) + '&';
}
return query.length ? query.substr(0, query.length - 1) : query;
};
// Override $http service's default transformRequest
$httpProvider.defaults.transformRequest = [function(data) {
return angular.isObject(data) && String(data) !== '[object File]' ? param(data) : data;
}];
});
It's not angular's fault. Angular is designed to work in JSON world. So when $http service send AJAX request, it send all your data as a payload, not as form-data so that your backend application can handle it. But jQuery does some things internally. You instruct jQuery's $ajax module to bind form-data as JSON but before sending AJAX request, it serialized JSON and add application/x-www-form-urlencoded header. This way your backend application able to received form-data in form of post parameters and not JSON.
但是你可以修改angular $http服务的默认行为
添加标题
序列化json
$httpParamSerializerJQLike是angular的内置服务,它以同样的方式序列化json。jQuery的参数。
$http({
method: 'POST',
url: 'request-url',
data: $httpParamSerializerJQLike(json-form-data),
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8;'
}
});
如果你需要一个插件先将表单数据序列化成JSON,可以使用这个插件https://github.com/marioizquierdo/jquery.serializeJSON
这可能是一个很晚的答案,但我认为最合适的方法是使用angular在使用$httpParamSerializer执行“get”请求时使用的同一段代码,它将不得不注入到你的控制器中
所以你可以简单地做下面的事情,而不需要使用Jquery,
美元http.post (url, httpParamSerializer美元({参数:val}))
app.controller('ctrl',function($scope,$http,$httpParamSerializer){
$http.post(url,$httpParamSerializer({param:val,secondParam:secondVal}));
}