使用Angular.js进行HTTP POST

20

我是新手,想使用Angular.js进行HTTP POST请求。我要访问一些参数仅为POST变量的PHP脚本。每个脚本返回一个JSON字符串。通常在HTML表单中,可以这样发出请求:

<form method="post" action="url.php">
<input name="this">
<input name="that">
<input value="Submit">
</form>
根据您的输入并在单击提交后,JSON数据1将返回类似于此的内容:{ "code" : 1 }
我无法访问脚本或托管它们的服务器。
我想知道Angular.js是否能够读取JSON数据1,将其与我的JSON数据2中定义的数据进行匹配,然后将它们输出到我的视图(<pre>data2</pre>)。
例如,如果检索到{ "code" : 1 },我希望我的JSON输出代码#1的值:
{ "code" : [
  { 1: "User already logged in." }, 
  { 2: "Wrong parameters, try again."}, 
  { 3: "etc., etc." }
 ] 
};

这是我的尝试:

<form ng-controller="PhpCtrl" name="f1">
<input type="text" name="name">
<input type="text" name="password">
<pre ng-model="codeStatus">{{codeStatus}}</pre>
<input type="submit" ng-click="add()" value="Submit">
</form>

function PhpCtrl($scope, $http, $templateCache) {
    $scope.method = 'POST';
    $scope.url = 'url.php';
    $scope.codeStatus = "";

    $scope.add = function() {

        $http({
            method: $scope.method, 
            url: $scope.url,
            headers: {'Content-Type': 'application/x-www-form-urlencoded'},  
            cache: $templateCache
        }).
        success(function(response) {
            $scope.codeStatus = response.data;
        }).
        error(function(response) {
            $scope.codeStatus = response || "Request failed";
        });
        return false;   
    };
}

到目前为止,它只向视图(post to the view)发布了“请求失败(Request failed)”的信息,虽然它正在处理HTTP/1.1 200。我知道我还有很长的路要走,但我会感激任何帮助。一旦我弄清楚如何向视图(post to the view)发布正确的JSON数据1,下一步就是匹配和输出相应的数据2。提前致谢!


也许请求失败是因为你在进行POST请求时没有发送数据,请尝试将所有表单字段放入FormData对象中,并在其中添加data: FormData作为$http请求的参数,然后发送请求,或者是因为headers不正确。希望这可以帮助到你。 - Yahya KACEM
谢谢您的回复。我不确定我是否做对了,但是我只需将表单数据包装在FormData中作为“JSON对象”吗?我尝试了这个http://pastebin.com/QMZSr4AZ,但仍然处理“请求失败”错误,所以我猜我仍然未能发送数据。 - matenji
两件事情:1)你不应该在$scope上设置这些值,$scope是用于模型绑定的,它上面的所有值都被监视,并且它们的值被应用于同名字段,这会影响性能。只需将它们设置为局部变量,例如var method = 'POST',它们将作为闭包的一部分在http函数中使用。2)你知道如何在Chrome/Firefox中进入JS调试器吗?使用它来检查响应。在Chrome右上角>开发者工具,你需要网络选项卡,如果你在错误函数中添加一个debugger;行,则还需要控制台。 - Chris Moschini
嗨 Chris,谢谢你的评论和建议!关于在$scope上进行模型绑定的问题,使用本地变量确实是有道理的,所以我会记住这个方法。我已经尝试过JS调试器了,但由于我正在本地测试,它一直抛出同源策略错误,因此我现在正在使用Firefox。 - matenji
3个回答

48

实际上问题出现在后端的PHP代码中,您需要以不同于通常的方式获取已发布的数据。以下方法对我有效:

function PhpCtrl($scope, $http, $templateCache) {
  var method = 'POST';
  var url = 'url.php';
  $scope.codeStatus = "";
  $scope.add = function() {
    var FormData = {
      'name' : document.f1.name.value,
      'password' : document.f1.password.value
    };
    $http({
      method: method,
      url: url,
      data: FormData,
      headers: {'Content-Type': 'application/x-www-form-urlencoded'},
      cache: $templateCache
    }).
    success(function(response) {
        $scope.codeStatus = response.data;
    }).
    error(function(response) {
        $scope.codeStatus = response || "Request failed";
    });
    return false;
  };
}

在 PHP 文件中:

$data = json_decode(file_get_contents("php://input"));
echo $data->name;
希望这有所帮助。

开发者Yahya尝试实现那个脚本,但是它显示无法从非对象中获取属性“name”。是否必须保留该行代码(echo $data->name;)呢? - matenji
1
不,那只是一个例子,需要的是在那之前的那一行,然后你需要进行数据处理,然后回显你想要的返回消息。 - Yahya KACEM
我的PHP版本是PHP 5.5.3,这对我来说很好用 #ta7yaISI #Ta7yaTounes - Mils
使用 PHP 5.3.13,parse_str(file_get_contents('php://input'), $data); 对我很有效。 - Ryan
这真是太有帮助了!非常感谢 @YahyaKACEM。干杯! - henser

21

虽然这是一篇旧帖子... 但我认为我的解决方案可能对其他人也有用。

我不喜欢这个

json_decode(file_get_contents("php://input"));

解决方案...基本上是因为它似乎违反了良好的实践(我可能在这方面有所错误)

这就是我解决它的方式(适用于上面的示例)

function PhpCtrl($scope, $http, $templateCache) {
  var method = 'POST';
  var url = 'url.php';
  $scope.codeStatus = "";
  $scope.add = function() {
    var FormData = {
      'name' : document.f1.name.value,
      'password' : document.f1.password.value
    };
    $http({
      method: method,
      url: url,
      data: $.param({'data' : FormData}),
      headers: {'Content-Type': 'application/x-www-form-urlencoded'},
      cache: $templateCache
    }).
    success(function(response) {
        $scope.codeStatus = response.data;
    }).
    error(function(response) {
        $scope.codeStatus = response || "Request failed";
    });
    return false;
  };
}

一旦这个完成了

data: $.param({'data' : FormData}),
headers: {'Content-Type': 'application/x-www-form-urlencoded'},

你可以像在PHP中一样访问数据。

$data = $_POST['data'];

$templateCache在请求数据中真的必要吗? - Jago
我不知道这个问题是否已经有了新的变化,但是对于我的情况,$.param() 不可用。我成功使用的方法是:$httpParamSerializerJQLike(FormData)。 - Miguel Suarez
好的,看起来你需要jQuery才能使它工作。否则$.param是未定义的。 - DijkeMark
是的...抱歉...应该提到这个使用了jQuery的$.params()函数。 - dGo
以下是独立的param函数:`var param = function(data) { var returnString = ''; for (var d in data) { if (data.hasOwnProperty(d)) { returnString += d + '=' + data[d] + '&'; } } return returnString.slice( 0, returnString.length - 1 ); };` - David Rhoderick
好的解决方案,但是PUT、DELETE和OPTIONS需要像@Yahya KACEM所说的那样从PHP方面做些改进。 - boctulus

4
一个可能的替代方案是使用XHR请求处理程序来序列化POST请求的有效载荷。
$httpProvider.interceptors.push(['$q', function($q) {
    return {
        request: function(config) {
            if (config.data && typeof config.data === 'object') {
                // Check https://gist.github.com/brunoscopelliti/7492579 for a possible way to implement the serialize function.
                config.data = serialize(config.data);
            }
            return config || $q.when(config);
        }
    };
}]);

此外,如果您之前没有这样做过,您还需要更改POST请求的默认内容类型标头:
$http.defaults.headers.post["Content-Type"] = 
    "application/x-www-form-urlencoded; charset=UTF-8;";

最近我在博客上写了一篇文章,其中包含更多关于这种方法的信息,以及XHR请求拦截器


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接