angularjs http 請求 php 無資料解決辦法
阿新 • • 發佈:2019-02-16
序
雖然angularjs自帶http請求,但是當它的後臺為php時,我們往往拿不到想要的資料(相同的請求用jQuery能正確返回結果)。其實這是因為angularjs預設的請求方式不適合php接收而已。因此我們需要修改或者使用其他的請求方式來實現與後臺的互動。
$http預設請求頭資訊
$http服務將會給所有請求自動建立HTTP頭。這個預設設定能完全的通過訪問$httpProvider.defaults.headers配置物件配置。目前包含默:
$httpProvider.defaults.headers.common
//-- Accept:application/json,text/plain
$httpProvider.defaults .headers.post
//-- Content-Type:application/json
$httpProvider.defaults.headers.put
//-- Content-Type:application/json
解決方法
以下案例均通過wampserver環境下的php後臺請求測試,如果非此類環境有可能拿不到想要的結果,請自行封裝其他方法解決。
以下案例的實現均需要有正常的php開發環境來支援,假如我們有這樣一個ajax.php檔案:
<?php
header('Content-type:text/html;charset=utf-8' );
if ($_GET) {
$msg = ['name' => $_GET['name'], 'type' => '這是get請求'];
echo json_encode($msg);
exit();
}
if ($_POST) {
$msg = ['name' => $_POST['name'], 'type' => '這是post請求'];
echo json_encode($msg);
exit();
}
$msg = ['type' => '這是其他請求'];
echo json_encode($msg);
方法一:封裝自定義httpService服務(推薦做法)
利用$httpParamSerializerJQLike和Content-Type設定來封裝自定義服務,可以友好解決這個問題,而且它可以像jQuery那樣發請求(注意自定義服務的呼叫方式,如果不明白什麼是服務,可以參考angularjs service 自定義服務 或者 angularjs factory (工廠服務))。
<!DOCTYPE html>
<html lang="zh">
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>angularjs service</title>
<meta name="author" content="loushengyue">
</head>
<body>
<div ng-app="app" ng-controller="ctrl">
<h1>請按F12檢視控制檯的console面板</h1>
</div>
<script src="https://cdn.bootcss.com/angular.js/1.6.9/angular.min.js"></script>
<script>
angular.module('app', [])
.controller('ctrl', ['$scope', 'httpService', function ($scope, httpService) {
var option = {
type: 'post',
url: './ajax.php',
data: {
name: 'loushengyue'
}
};
httpService.request(option).then(function (res) {
console.log(res);
}, function (error) {
console.log(error);
})
}])
.service('httpService', ['$http', '$q', '$httpParamSerializerJQLike',
function ($http, $q, $httpParamSerializerJQLike) {
//$httpParamSerializerJQLike表示它可以像jquery那樣序列化資料
this.request = function (option) {
if (!option || !option.url) {
throw new Error('option or option.url is undefind.');
}
var def = $q.defer(), _method,
_data = option.data ? option.data : {};
option.method = option.method ? option.method : (option.type ? option.type : 'get');
_method = angular.uppercase(option.method);
if (_method === 'GET' && !option.params) {
option.params = _data; //使get請求支援data傳參
}
if (_method === 'POST') {
var _config = {
headers: {"Content-Type": "application/x-www-form-urlencoded"}
};
option.data = $httpParamSerializerJQLike(_data);
angular.merge(option, _config);//合併請求引數使post請求類似jquery一樣
}
$http(option).then(function (res) {
def.resolve(res.data)
}, function (error) {
def.reject(error)
});
return def.promise;
};
return this;
}])
</script>
</body>
</html>
方法二: 修改$httpProvider配製
這是一種各大部落格網友推薦的一種做法,它能夠一次性配製所有的$http內建服務的post請求方式(不過這種配製是有漏洞的,它不支援複雜引數的傳遞)。
<div ng-app="app" ng-controller="ctrl">
<h1>請按F12檢視控制檯的console面板</h1>
<div>
<button ng-click="getRequest()">get request test</button>
<br>
<button ng-click="postRequest()">post request test</button>
</div>
</div>
<script src="https://cdn.bootcss.com/angular.js/1.6.9/angular.min.js"></script>
<script>
angular.module('app', [])
.config(['$httpProvider', function ($httpProvider) {
$httpProvider.defaults.transformRequest = function (data) {
var arr = [];
angular.forEach(data, function (val, key) {
arr.push(encodeURIComponent(key) + '=' + encodeURIComponent(val));
});
return arr.join('&');
};
//通過下面這一行你能看到你$http的預設配置資訊
console.log($httpProvider.defaults.headers);//請自行刪除本行
$httpProvider.defaults.headers = {
post: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}
}])
.controller('ctrl', ['$scope', '$http', function ($scope, $http) {
$scope.getRequest = function () {
$http({
method: 'get',//切記這裡是method!!jQuery用的是type
url: './ajax.php?name=loushengyue&age=30'
//angularjs的get請求沒有data傳參,需要拼接url或者用params物件
}).then(function (res) {
console.log(res.data);
alert('get success')
})
};
$scope.postRequest = function () {
$http({
method: 'post', //切記這裡是method!!jQuery用的是type
url: './ajax.php',
data: {
name: 'loushengyue',
age: 30,
sex: 'male'
}
}).then(function (res) {
console.log(res.data);
alert('post success');
})
};
}])
</script>
方法三:修改$http配置
<div ng-app="app" ng-controller="ctrl">
<h1>請按F12檢視控制檯的console面板</h1>
<div>
<button ng-click="getRequest()">get request test</button>
<br>
<button ng-click="postRequest()">post request test</button>
</div>
</div>
<script src="https://cdn.bootcss.com/angular.js/1.6.9/angular.min.js"></script>
<script>
angular.module('app', [])
.controller('ctrl', ['$scope', '$http', '$httpParamSerializerJQLike',
function ($scope, $http, $httpParamSerializerJQLike) {
$scope.getRequest = function () {
$http({
method: 'get',//切記這裡是method!!jQuery用的是type
url: './ajax.php',
params: {
name: 'test',
age: 18
}
//angularjs的get請求沒有data傳參,需要拼接url或者用params物件
}).then(function (res) {
console.log(res.data);
alert('get success')
})
};
$scope.postRequest = function () {
$http({
method: 'post', //切記這裡是method!!jQuery用的是type
url: './ajax.php',
data: $httpParamSerializerJQLike({
name: 'loushengyue',
age: 30,
sex: 'male'
}),
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}).then(function (res) {
console.log(res.data);
alert('post success');
})
};
}])
</script>
$httpParamSerializerJQLike部分原碼展示
function jQueryLikeParamSerializer(params) {
if (!params) return '';
var parts = [];
serialize(params, '', true);
return parts.join('&');
function serialize(toSerialize, prefix, topLevel) {
if (toSerialize === null || isUndefined(toSerialize)) return;
if (isArray(toSerialize)) {
forEach(toSerialize, function (value, index) {
serialize(value, prefix + '[' + (isObject(value) ? index : '') + ']');
});
} else if (isObject(toSerialize) && !isDate(toSerialize)) {
forEachSorted(toSerialize, function (value, key) {
serialize(value, prefix +
(topLevel ? '' : '[') +
key +
(topLevel ? '' : ']'));
});
} else {
parts.push(encodeUriQuery(prefix) + '=' + encodeUriQuery(serializeValue(toSerialize)));
}
}
}
function encodeUriQuery(val, pctEncodeSpaces) {
return encodeURIComponent(val).
replace(/%40/gi, '@').
replace(/%3A/gi, ':').
replace(/%24/g, '$').
replace(/%2C/gi, ',').
replace(/%3B/gi, ';').
replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));
}
function serializeValue(v) {
if (isObject(v)) {
return isDate(v) ? v.toISOString() : toJson(v);
}
return v;
}