【问题标题】:AngularJS HTTP post to PHP and undefinedAngularJS HTTP 发布到 PHP 和未定义
【发布时间】:2013-03-07 07:01:53
【问题描述】:

我有一个带有标签ng-submit="login()的表单

该函数在 javascript 中可以正常调用。

function LoginForm($scope, $http)
{
    $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';

    $scope.email    = "fsdg@sdf.com";
    $scope.password = "1234";

    $scope.login = function()
    {
        data = {
            'email' : $scope.email,
            'password' : $scope.password
        };

        $http.post('resources/curl.php', data)
        .success(function(data, status, headers, config)
        {
            console.log(status + ' - ' + data);
        })
        .error(function(data, status, headers, config)
        {
            console.log('error');
        });
    }
}

我从 PHP 文件收到 200 OK 响应,但是,返回的数据显示 emailpassword 未定义。这是我所有的php

<?php
$email = $_POST['email'];
$pass  = $_POST['password'];
echo $email;
?>

知道为什么我得到未定义的POST 值吗?

编辑

我想指出,因为这似乎是一个流行的问题(但它很旧),.success.error 已被弃用,您应该使用.then,正如@James Gentes 在评论中指出的那样

【问题讨论】:

  • 您是否查看了开发人员工具的网络选项卡? $http 中传递了什么值?
  • 在网络选项卡中,Form-Data 下显示为{"email":"fsdg@sdf.com","password":"1234"}
  • @Ronnie 看起来像 JSON。尝试print_r($_POST);,然后在右侧索引上尝试json_decode()
  • echo 'test'; 工作正常。我当然指向正确的文件
  • 请注意 .success 和 .error 已被弃用并替换为 .then (docs.angularjs.org/api/ng/service/$http)

标签: php javascript angularjs


【解决方案1】:

angularjs .post() 默认 Content-type 标头为 application/json。您将覆盖它以传递表单编码的数据,但是您没有更改您的 data 值以传递适当的查询字符串,因此 PHP 不会像您期望的那样填充 $_POST

我的建议是只使用 application/json 的默认 angularjs 设置作为标题,读取 PHP 中的原始输入,然后反序列化 JSON。

在 PHP 中可以这样实现:

$postdata = file_get_contents("php://input");
$request = json_decode($postdata);
$email = $request->email;
$pass = $request->password;

或者,如果您严重依赖$_POST 功能,您可以形成一个类似email=someemail@email.com&amp;password=somepassword 的查询字符串并将其作为数据发送。确保此查询字符串是 URL 编码的。如果手动构建(而不是使用类似 jQuery.serialize() 的东西),Javascript 的 encodeURIComponent() 应该可以为您解决问题。

【讨论】:

  • 不是不尊重您的知识,但使用file_get_contents("php://input"); 似乎有点像黑客,不是吗?我从来没有听说过这个。需要发生什么,所以我可以像 $_POST['email']; 一样引用它
  • @Ronnie 这不是黑客。这实际上取决于您希望如何设置 Web 服务。如果要发送和检索 JSON,则需要使用原始输入,因为不会填充 $_POST
  • @lepe 我不清楚链接的问题/答案与我的答案有何关系。这里没有讨论需要序列化 ​​javascript 对象。
  • @lascort 解决方案确实没有太大区别。在我的解决方案中,我没有将数据填充到 $_POST 中,而是更喜欢用户定义的变量。一般来说,这对我来说更有意义,因为在处理 JSON 序列化数据时,您可能正在使用对象或数字索引数组。我不建议将数字索引数组添加到 $_POST,因为这将是一种非典型用途。我通常也避免将数据放入任何用于输入数据的超全局变量中。
  • @ItsmeJulian 没有绝对正确的答案。这可能真的取决于您的应用程序的架构方式。如果您正在与使用/交付 JSON 的 REST 服务进行交互,那么我可能会坚持使用 JSON 内容类型。如果我主要使用可以生成 HTML 或 HTML 片段的端点,或者使用基本的表单发布作为 AJAX 的后备,那么我可能倾向于坚持使用表单编码。
【解决方案2】:

我在服务器端做,在我的 init 文件的开头,就像一个魅力,你不必在 angular 或现有的 php 代码中做任何事情:

if ($_SERVER['REQUEST_METHOD'] == 'POST' && empty($_POST))
    $_POST = json_decode(file_get_contents('php://input'), true);

【讨论】:

  • 如果 $_POST 为空,您应该转换结果:$_POST = (array) json_decode(file_get_contents('php://input'), true)
  • 我真的不明白为什么 PHP 人不自己实现这个,他们真的希望总是 url 编码的帖子??
  • @Bludream 我不明白为什么有人希望 PHP 做预期的事情。它始终违反最小意外原则。
  • 这似乎是一种非常脆弱的方法,除非您绝对知道发布的数据表示关联数组(JSON 中的对象表示)。如果 JSON 包含数字索引的数组表示怎么办?在这种情况下,$_POST 最终会得到一个数字索引数组,这在依赖于一致的$_POST 超全局行为的系统其他部分中将是非常意外的行为。
  • 当然,我只在角度驱动的应用程序中使用它,而且我非常彻底地验证了我的 POST 数据,看不出这怎么会是个问题...
【解决方案3】:

在我正在开发的 API 中,我有一个基本控制器,在它的 __construct() 方法中,我有以下内容:

if(isset($_SERVER["CONTENT_TYPE"]) && strpos($_SERVER["CONTENT_TYPE"], "application/json") !== false) {
    $_POST = array_merge($_POST, (array) json_decode(trim(file_get_contents('php://input')), true));
}

这使我可以在需要时将 json 数据简单地引用为 $_POST["var"]。效果很好。

这样,如果经过身份验证的用户连接到一个库,例如 jQuery,该库发送带有默认 Content-Type: application/x-www-form-urlencoded 或 Content-Type: application/json 的 post 数据,API 将在没有响应的情况下响应错误,并使 API 对开发人员更加友好。

希望这会有所帮助。

【讨论】:

    【解决方案4】:

    因为 PHP 本身不接受 JSON 'application/json' 一种方法是从 angular 更新您的标头和参数,以便您的 api 可以直接使用数据。

    首先,参数化你的数据:

    data: $.param({ "foo": $scope.fooValue })
    

    然后,将以下内容添加到您的$http

     headers: {
         'Content-Type' : 'application/x-www-form-urlencoded; charset=UTF-8'
     }, 
    

    如果您的所有请求都发往 PHP,则可以在配置中全局设置参数,如下所示:

    myApp.config(function($httpProvider) {
        $httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
    });
    

    【讨论】:

      【解决方案5】:

      Angular Js 演示代码:-

      angular.module('ModuleName',[]).controller('main', ['$http', function($http){
      
                      var formData = { password: 'test pwd', email : 'test email' };
                      var postData = 'myData='+JSON.stringify(formData);
                      $http({
                              method : 'POST',
                              url : 'resources/curl.php',
                              data: postData,
                              headers : {'Content-Type': 'application/x-www-form-urlencoded'}  
      
                      }).success(function(res){
                              console.log(res);
                      }).error(function(error){
                              console.log(error);
              });
      
              }]);
      

      服务器端代码:-

      <?php
      
      
      // it will print whole json string, which you access after json_decocde in php
      $myData = json_decode($_POST['myData']);
      print_r($myData);
      
      ?>
      

      由于角度行为,PHP 服务器上的正常发布行为没有直接的方法,因此您必须在 json 对象中对其进行管理。

      【讨论】:

      • 这是不正确的。请参阅上面直接从 PHP 原始输入读取 JSON 的答案。这比将 JSON 混合到查询字符串中要简单得多。
      • .success.error 方法已被弃用,并已从 AngularJS 框架中删除。
      【解决方案6】:

      在将表单数据作为第二个参数传递给 .post() 之前,您需要反序列化表单数据。您可以使用 jQuery 的 $.param (data) 方法来实现这一点。 然后你就可以在服务器端引用它,比如 $.POST ['email'];

      【讨论】:

        【解决方案7】:

        这是最好的解决方案 (IMO),因为它不需要 jQuery 和 JSON 解码:

        来源: https://wordpress.stackexchange.com/a/179373 和:https://stackoverflow.com/a/1714899/196507

        总结:

        //Replacement of jQuery.param
        var serialize = function(obj, prefix) {
          var str = [];
          for(var p in obj) {
            if (obj.hasOwnProperty(p)) {
              var k = prefix ? prefix + "[" + p + "]" : p, v = obj[p];
              str.push(typeof v == "object" ?
                serialize(v, k) :
                encodeURIComponent(k) + "=" + encodeURIComponent(v));
            }
          }
          return str.join("&");
        };
        
        //Your AngularJS application:
        var app = angular.module('foo', []);
        
        app.config(function ($httpProvider) {
            // send all requests payload as query string
            $httpProvider.defaults.transformRequest = function(data){
                if (data === undefined) {
                    return data;
                }
                return serialize(data);
            };
        
            // set all post requests content type
            $httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
        });
        

        例子:

        ...
           var data = { id: 'some_id', name : 'some_name' };
           $http.post(my_php_url,data).success(function(data){
                // It works!
           }).error(function() {
                // :(
           });
        

        PHP 代码:

        <?php
            $id = $_POST["id"];
        ?>
        

        【讨论】:

        • 怎么样:JSON.stringify('{ id: 'some_id', name : 'some_name' }')$httpParamSerializer 用于客户端转换?
        【解决方案8】:

        这是一个老问题,但值得一提的是,在 Angular 1.4 中添加了 $httpParamSerializer,并且在使用 $http.post 时,如果我们使用 $httpParamSerializer(params) 传递参数,一切都像普通的 post 请求一样工作,并且没有服务器端需要 JSON 反序列化。

        https://docs.angularjs.org/api/ng/service/$httpParamSerializer

        【讨论】:

          【解决方案9】:

          在使用 Angular 和 PHP 时,我花了几个小时才明白这一点。 在 $_POST 中发布数据不会发送到 PHP

          在 PHP 代码中执行以下操作。 - 创建一个变量 $angular_post_params - 然后执行以下操作 $angular_http_params = (array)json_decode(trim(file_get_contents('php://input')));

          现在您可以像从 $_POST 一样访问您的参数了

          $angular_http_params["key"]

          如果你想知道 javascript....这就是我使用的

              var myApp = angular.module('appUsers', []);
              //var post_params = $.param({ request_type: "getListOfUsersWithRolesInfo" });
              var dataObj = {
                  task_to_perform: 'getListOfUsersWithRolesInfo'
              };
          
              myApp.controller('ctrlListOfUsers', function ($scope, $http) {
                  $http({
                      method: 'POST',
                      dataType: 'json',
                      url: ajax_processor_url,
                      headers: {
                          'Content-Type': 'application/json'
                      },
                      data: dataObj,
                      //transformRequest: function(){},
                      timeout: 30000,
                      cache: false
                  }).
                  success(function (rsp) {
                      console.log("success");
                      console.log(rsp);
                  }).
                  error(function (rsp) {
                      console.log("error");
                  });
              });
          

          【讨论】:

          • 对于新手...不要忘记将 ng-app 和 ng-controller 指令添加到页面上的内容容器容器中 :)
          • .success.error 方法已被弃用,并已从 AngularJS 框架中删除。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-01-08
          • 2013-05-28
          • 2012-11-25
          • 1970-01-01
          • 1970-01-01
          • 2018-04-19
          • 1970-01-01
          相关资源
          最近更新 更多