AngularJS HTTP đăng lên PHP và không xác định


107

Tôi có một biểu mẫu với thẻ ng-submit="login()

Hàm được gọi là tốt trong 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');
        });
    }
}

Tôi nhận được phản hồi 200 OK từ tệp PHP, tuy nhiên, dữ liệu trả về cho biết điều đó emailpasswordkhông được xác định. Đây là tất cả php tôi có

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

Bất kỳ ý tưởng tại sao tôi nhận được POSTcác giá trị không xác định ?

BIÊN TẬP

Tôi muốn chỉ ra vì đây có vẻ là một câu hỏi phổ biến (nhưng nó đã cũ) .success.errorđã không còn được dùng nữa và bạn nên sử dụng .thennhư @James Gentes đã chỉ ra trong phần kết luận


2
Bạn đã xem tab mạng của các công cụ dành cho nhà phát triển của mình chưa? Giá trị nào được chuyển vào $http?
Marcel Korpel

1
Trong tab mạng, dưới Form-Datanó cho biết{"email":"fsdg@sdf.com","password":"1234"}
Ronnie

@Ronnie Có vẻ giống JSON. Hãy thử print_r($_POST);và sau đó thử json_decode()đúng chỉ số
HamZa

1
echo 'test';hoạt động tốt. Tôi chắc chắn đang trỏ đến đúng tệp
Ronnie

1
Lưu ý rằng .success và .error đã không còn được dùng nữa và được thay thế bằng .then ( docs.angularjs.org/api/ng/service/$http )
James Gentes

Câu trả lời:


228

anglejs .post()mặc định tiêu đề Loại nội dung thành application/json. Bạn đang ghi đè điều này để chuyển dữ liệu được mã hóa biểu mẫu, tuy nhiên bạn không thay đổi datagiá trị của mình để chuyển một chuỗi truy vấn thích hợp, vì vậy PHP không được điền $_POSTnhư bạn mong đợi.

Đề xuất của tôi sẽ là chỉ sử dụng cài đặt anglejs mặc định application/jsonlàm tiêu đề, đọc đầu vào thô trong PHP, sau đó giải mã hóa JSON.

Điều đó có thể đạt được trong PHP như thế này:

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

Ngoài ra, nếu bạn phụ thuộc nhiều vào $_POSTchức năng, bạn có thể tạo một chuỗi truy vấn như email=someemail@email.com&password=somepasswordvà gửi chuỗi đó dưới dạng dữ liệu. Đảm bảo rằng chuỗi truy vấn này được mã hóa URL. Nếu được xây dựng theo cách thủ công (trái ngược với việc sử dụng một cái gì đó như vậy jQuery.serialize()), thì Javascript encodeURIComponent()sẽ giúp bạn.


7
Không tôn trọng kiến ​​thức của bạn, nhưng sử dụng file_get_contents("php://input");có vẻ giống như một vụ hack, phải không? Tôi chưa bao giờ nghe nói về điều này. Điều gì cần xảy ra để tôi có thể tham khảo nó như$_POST['email'];
Ronnie

6
@Ronnie Nó không phải là một hack. Nó thực sự phụ thuộc vào cách bạn muốn thiết lập dịch vụ web của mình. Nếu bạn muốn gửi và truy xuất JSON, bạn cần phải làm việc với đầu vào thô vì $_POSTsẽ không được điền.
Mike Brant

1
@lepe Tôi không rõ câu hỏi / câu trả lời được liên kết có liên quan như thế nào đến câu trả lời của tôi. Không có cuộc thảo luận nào về việc cần tuần tự hóa một đối tượng javascript ở đây.
Mike Brant

2
@lascort thực sự không có nhiều khác biệt so với các giải pháp thực sự. Trong giải pháp của tôi, tôi không điền dữ liệu vào $ _POST, thay vào đó tôi thích một biến do người dùng xác định. Nói chung, điều này có ý nghĩa hơn đối với tôi ở chỗ khi làm việc với dữ liệu được tuần tự hóa JSON, bạn có thể đang làm việc với các đối tượng wth hoặc các mảng được lập chỉ mục số. Tôi sẽ không đề xuất thêm một mảng được lập chỉ mục số vào $ _POST, vì đây sẽ là cách sử dụng không điển hình. Nói chung, tôi cũng tránh đưa dữ liệu vào bất kỳ superglobals nào được sử dụng cho dữ liệu đầu vào.
Mike Brant

1
@ItsmeJulian không có câu trả lời đúng tuyệt đối. Nó thực sự có thể phụ thuộc vào cách ứng dụng của bạn được cấu trúc. Nếu bạn đang tương tác với một dịch vụ REST đang sử dụng / phân phối JSON, thì tôi có thể sẽ gắn bó với loại nội dung JSON. Nếu tôi đang làm việc chủ yếu với một điểm cuối có thể tạo ra các đoạn HTML hoặc HTML hoặc sử dụng đăng biểu mẫu cơ bản làm dự phòng cho AJAX, thì tôi có thể có khuynh hướng gắn bó với mã hóa biểu mẫu.
Mike Brant

41

Tôi làm điều đó ở phía máy chủ, khi bắt đầu tệp init của tôi, hoạt động giống như một sự quyến rũ và bạn không phải làm bất cứ điều gì trong mã php góc cạnh hoặc hiện có:

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

3
bạn nên đúc kết quả của bạn trong trường hợp $ _POST trống: $_POST = (array) json_decode(file_get_contents('php://input'), true).
M'sieur Toph '

Tôi thực sự không hiểu tại sao những người PHP không tự thực hiện điều này, Họ thực sự mong đợi các bài đăng được mã hóa url luôn ??
azerafati

@Bludream Tôi không hiểu tại sao mọi người lại mong đợi PHP làm những gì được mong đợi. Nó vi phạm nguyên tắc ít gây ngạc nhiên nhất mọi lúc.
doug65536,

Đây có vẻ như là một cách tiếp cận rất mỏng manh trừ khi bạn hoàn toàn biết rằng dữ liệu POSTed đại diện cho một mảng kết hợp (một biểu diễn đối tượng trong JSON). Điều gì sẽ xảy ra nếu JSON chứa một biểu diễn mảng được lập chỉ mục số? $_POSTcuối cùng sẽ nhận được một mảng được lập chỉ mục bằng số trong trường hợp này, một điều gì đó sẽ là hành vi rất bất ngờ trong phần khác của hệ thống dựa trên $_POSThành vi siêu toàn cầu nhất quán .
Mike Brant

1
Tôi chỉ sử dụng trong các ứng dụng này được hỗ trợ góc, tất nhiên, và tôi xác nhận dữ liệu POST của tôi rất kỹ lưỡng, không thấy thế nào điều này có thể là một vấn đề ...
valmarv

14

Trong API mà tôi đang phát triển, tôi có một bộ điều khiển cơ sở và bên trong phương thức __construct () của nó, tôi có những thứ sau:

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));
}

Điều này cho phép tôi chỉ cần tham chiếu dữ liệu json dưới dạng $ _POST ["var"] khi cần. Hoạt động tuyệt vời.

Theo cách đó, nếu người dùng đã xác thực kết nối với thư viện, một jQuery gửi dữ liệu bài đăng với mặc định là Loại nội dung: ứng dụng / x-www-form-urlencoded hoặc Loại nội dung: ứng dụng / json, API sẽ phản hồi mà không có lỗi và sẽ làm cho API thân thiện hơn với nhà phát triển.

Hi vọng điêu nay co ich.


11

Bởi vì PHP tự nhiên không chấp nhận JSON 'application/json'Một cách tiếp cận là cập nhật tiêu đề và tham số của bạn từ góc độ để api của bạn có thể sử dụng dữ liệu trực tiếp.

Đầu tiên , hãy tham số hóa dữ liệu của bạn:

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

Sau đó , thêm phần sau vào$http

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

Nếu tất cả các yêu cầu của bạn đều chuyển sang PHP, các tham số có thể được đặt toàn cục trong cấu hình như sau:

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

8

Mã Demo 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);
        });

        }]);

Mã phía máy chủ: -

<?php


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

?>

Do hành vi góc cạnh không có phương thức trực tiếp cho hành vi đăng bài bình thường tại máy chủ PHP, vì vậy bạn phải quản lý nó trong các đối tượng json.


1
Điều này là không đúng. Xem câu trả lời ở trên trong đó JSON được đọc trực tiếp từ đầu vào thô PHP. Điều này đơn giản hơn nhiều so với việc trộn JSON vào chuỗi truy vấn.
Mike Brant

Các phương thức .success.errorkhông được chấp nhận và đã bị xóa khỏi khung AngularJS.
georgeawg

6

Bạn cần giải mã dữ liệu biểu mẫu của mình trước khi chuyển nó làm tham số thứ hai cho .post (). Bạn có thể đạt được điều này bằng cách sử dụng phương thức $ .param (data) của jQuery. Sau đó, bạn sẽ có thể ở phía máy chủ để tham chiếu nó như $ .POST ['email'];


6

Đây là giải pháp tốt nhất (IMO) vì nó không yêu cầu jQuery và không cần giải mã JSON:

Nguồn: https://wordpress.stackexchange.com/a/179373 và: https://stackoverflow.com/a/1714899/196507

Tóm lược:

//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';
});

Thí dụ:

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

Mã PHP:

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

Điều gì về: JSON.stringify('{ id: 'some_id', name : 'some_name' }')hoặc $httpParamSerializerđối với chuyển đổi phía khách hàng?
qrtLs

5

Đó là một câu hỏi cũ nhưng cần đề cập rằng trong Angular 1.4 $ httpParamSerializer được thêm vào và khi sử dụng $ http.post, nếu chúng ta sử dụng $ httpParamSerializer (params) để chuyển các tham số, mọi thứ hoạt động giống như một yêu cầu đăng thông thường và không có JSON deserializing. cần thiết ở phía máy chủ.

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


1

Tôi đã mất hàng giờ để hiểu điều đó trong khi làm việc với Angular và PHP. Dữ liệu đăng sẽ không được chuyển sang PHP trong $ _POST

trong mã PHP làm như sau. - Tạo một biến $ angle_post_params - Sau đó làm như sau $angular_http_params = (array)json_decode(trim(file_get_contents('php://input')));

bây giờ bạn có thể truy cập các thông số của mình giống như bạn làm từ $ _POST

$angular_http_params["key"]

trong trường hợp bạn thắc mắc về javascript .... đây là những gì tôi đã sử dụng

    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");
        });
    });

cho người mới ... Đừng quên có ng-app và ng-điều khiển chỉ thị bổ sung vào thùng chứa giữ nội dung của bạn trên trang :)
Talha

Các phương thức .success.errorkhông được chấp nhận và đã bị xóa khỏi khung AngularJS.
georgeawg
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.