AngularJS HTTP โพสต์ไปยัง PHP และไม่ได้กำหนด


107

ฉันมีแบบฟอร์มพร้อมแท็ก ng-submit="login()

ฟังก์ชันนี้เรียกได้ว่าดีในจาวาสคริปต์

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

ฉันได้รับการตอบกลับ 200 OK จากไฟล์ PHP อย่างไรก็ตามข้อมูลที่ส่งคืนบอกว่าemailและpasswordไม่ได้กำหนด นี่คือ php ทั้งหมดที่ฉันมี

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

มีความคิดว่าทำไมฉันถึงได้รับPOSTค่าที่ไม่ได้กำหนด?

แก้ไข

ฉันอยากจะชี้ให้เห็นว่านี่เป็นคำถามยอดนิยม (แต่มันก็เก่าแล้ว) .successและ.errorเลิกใช้แล้วและคุณควรใช้.thenตามที่ @James Gentes ระบุไว้ในคอมเมนต์


2
คุณดูแท็บเครือข่ายของเครื่องมือสำหรับนักพัฒนาของคุณหรือไม่ ส่งผ่านค่า$httpอะไร
Marcel Korpel

1
ในแท็บเครือข่ายข้างใต้มีForm-Dataข้อความว่า{"email":"fsdg@sdf.com","password":"1234"}
Ronnie

@Ronnie ดูเหมือน JSON ลองprint_r($_POST);แล้วลองjson_decode()ดัชนีที่ถูกต้อง
HamZa

1
echo 'test';ใช้งานได้ดี ฉันกำลังชี้ไปที่ไฟล์ที่ถูกต้อง
Ronnie

1
โปรดทราบว่า .success และ. error ถูกเลิกใช้แล้วและแทนที่ด้วย. แล้ว ( docs.angularjs.org/api/ng/service/$http )
James Gentes

คำตอบ:


228

angularjs ค่าเริ่มต้นส่วนหัวของชนิดของเนื้อหาที่จะ.post() application/jsonคุณกำลังลบล้างสิ่งนี้เพื่อส่งผ่านข้อมูลที่เข้ารหัสแบบฟอร์มอย่างไรก็ตามคุณไม่ได้เปลี่ยนdataค่าของคุณเพื่อส่งผ่านสตริงการสืบค้นที่เหมาะสมดังนั้น PHP จึงไม่ได้รับการเติมข้อมูล$_POSTตามที่คุณคาดหวัง

ข้อเสนอแนะของฉันคือใช้การตั้งค่า angularjs เริ่มต้นของapplication/jsonเป็นส่วนหัวอ่านอินพุตดิบใน PHP จากนั้นจึงยกเลิกการกำหนดค่า JSON

ที่สามารถทำได้ใน PHP ดังนี้:

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

อีกวิธีหนึ่งหากคุณพึ่งพา$_POSTฟังก์ชันการทำงานเป็นอย่างมากคุณสามารถสร้างสตริงแบบสอบถามเช่นemail=someemail@email.com&password=somepasswordและส่งเป็นข้อมูลได้ ตรวจสอบให้แน่ใจว่าสตริงการสืบค้นนี้เข้ารหัส URL หากสร้างขึ้นด้วยตนเอง (ตรงข้ามกับการใช้สิ่งที่ชอบjQuery.serialize()) Javascript encodeURIComponent()ควรทำเคล็ดลับให้คุณ


7
ไม่ได้ดูหมิ่นความรู้ของคุณ แต่การใช้งานfile_get_contents("php://input");ดูเหมือนเป็นการแฮ็กไม่ใช่เหรอ? ฉันไม่เคยได้ยินเรื่องนี้ ต้องเกิดอะไรขึ้นฉันจึงสามารถอ้างอิงได้เช่น$_POST['email'];
Ronnie

6
@ รอนนี่ไม่ใช่แฮ็ค ขึ้นอยู่กับว่าคุณต้องการตั้งค่าบริการเว็บของคุณอย่างไร หากคุณต้องการส่งและดึงข้อมูล JSON คุณต้องทำงานกับอินพุตดิบเนื่องจาก$_POSTจะไม่ถูกเติมข้อมูล
Mike Brant

1
@lepe ไม่ชัดเจนสำหรับฉันว่าคำถาม / คำตอบที่เชื่อมโยงเกี่ยวข้องกับคำตอบของฉันอย่างไร ไม่มีการอภิปรายเกี่ยวกับความจำเป็นในการทำให้เป็นอนุกรมวัตถุจาวาสคริปต์ที่นี่
Mike Brant

2
@lascort ไม่มีความแตกต่างในการแก้ปัญหามากนัก ในโซลูชันของฉันฉันไม่ได้เติมข้อมูลลงใน $ _POST โดยเลือกใช้ตัวแปรที่ผู้ใช้กำหนดแทน โดยทั่วไปสิ่งนี้มีความหมายสำหรับฉันมากขึ้นเมื่อทำงานกับข้อมูลที่ทำให้เป็นอนุกรม JSON คุณอาจกำลังทำงานกับอ็อบเจ็กต์หรืออาร์เรย์ที่จัดทำดัชนีเป็นตัวเลข ฉันไม่แนะนำให้เพิ่มอาร์เรย์ที่จัดทำดัชนีเป็นตัวเลขให้กับ $ _POST เนื่องจากจะเป็นการใช้งานที่ผิดปกติ ฉันยังมักจะไม่ใส่ข้อมูลลงใน superglobals ใด ๆ ที่ใช้สำหรับข้อมูลอินพุต
Mike Brant

1
@ItsmeJulian ไม่มีคำตอบที่ถูกต้องแน่นอน อาจขึ้นอยู่กับว่าแอปพลิเคชันของคุณได้รับการออกแบบอย่างไร หากคุณกำลังโต้ตอบกับบริการ REST ที่ใช้งาน / ส่งมอบ JSON ฉันอาจจะยึดติดกับประเภทเนื้อหา JSON ถ้าฉันทำงานเป็นส่วนใหญ่กับปลายทางที่สามารถสร้างส่วน HTML หรือ HTML หรือใช้การโพสต์รูปแบบพื้นฐานเป็นทางเลือกกลับไปยัง AJAX ฉันอาจมีแนวโน้มที่จะยึดติดกับการเข้ารหัสแบบฟอร์ม
Mike Brant

41

ฉันทำที่ฝั่งเซิร์ฟเวอร์ในตอนเริ่มต้นของไฟล์ init ของฉันทำงานได้อย่างมีเสน่ห์และคุณไม่ต้องทำอะไรในเชิงมุมหรือโค้ด php ที่มีอยู่:

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

3
คุณควรโยนผลของคุณในกรณี $ _POST $_POST = (array) json_decode(file_get_contents('php://input'), true)ว่างเปล่า:
M'sieur Toph '12

ฉันไม่เข้าใจจริงๆว่าทำไมพวก PHP ถึงไม่ใช้สิ่งนี้ด้วยตัวเองพวกเขาคาดหวังว่าโพสต์ที่เข้ารหัส URL เสมอ
azerafati

@Bludream ฉันไม่เข้าใจว่าทำไมใคร ๆ ถึงคาดหวังให้ PHP ทำในสิ่งที่คาดหวัง มันละเมิดหลักการของความประหลาดใจน้อยที่สุดตลอดเวลา
doug65536

ดูเหมือนว่าจะเป็นวิธีการที่เปราะบางมากเว้นแต่คุณจะรู้อย่างแท้จริงว่าข้อมูลที่โพสต์นั้นแสดงถึงอาร์เรย์ที่เชื่อมโยง (การแสดงวัตถุใน JSON) จะเกิดอะไรขึ้นถ้า JSON มีการแทนค่าอาร์เรย์ที่เป็นตัวเลข $_POSTจะลงเอยด้วยการได้รับอาร์เรย์ที่จัดทำดัชนีเป็นตัวเลขในกรณีนี้สิ่งที่อาจเป็นพฤติกรรมที่ไม่คาดคิดในส่วนอื่น ๆ ของระบบที่อาศัย$_POSTพฤติกรรมของ superglobal ที่สอดคล้องกัน
Mike Brant

1
แน่นอนฉันใช้สิ่งนี้ในแอปพลิเคชั่นเชิงมุมเท่านั้นและฉันตรวจสอบข้อมูล POST ของฉันอย่างละเอียดมากไม่เห็นว่าจะเป็นปัญหาได้อย่างไร ...
valmarv

14

ใน 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 API จะตอบสนองโดยไม่มีข้อผิดพลาดและจะ ทำให้ API เป็นมิตรกับนักพัฒนาซอฟต์แวร์มากขึ้น

หวังว่านี่จะช่วยได้


11

เนื่องจาก PHP ไม่ยอมรับ'application/json'วิธีJSON One โดยกำเนิดคือการอัปเดตส่วนหัวและพารามิเตอร์ของคุณจากเชิงมุมเพื่อให้ 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';
});

8

รหัสสาธิต 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


1
สิ่งนี้ไม่ถูกต้อง ดูคำตอบด้านบนโดยที่ JSON อ่านโดยตรงจากอินพุตดิบของ PHP ตรงไปตรงมากว่าการผสม JSON ลงในสตริงการสืบค้น
Mike Brant

.successและ.errorวิธีการเลิกใช้แล้วและได้ถูกลบออกจากกรอบ AngularJS
georgeawg

6

คุณต้องยกเลิกการกำหนดค่าเริ่มต้นข้อมูลแบบฟอร์มของคุณก่อนที่จะส่งต่อเป็นพารามิเตอร์ที่สองไปยัง. post () คุณสามารถทำได้โดยใช้วิธี $ .param (data) ของ jQuery จากนั้นคุณจะสามารถอ้างอิงได้ทางฝั่งเซิร์ฟเวอร์เช่น $ .POST ['email'];


6

นี่เป็นทางออกที่ดีที่สุด (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สำหรับการแปลงฝั่งไคลเอ็นต์?
qrtLs

5

เป็นคำถามเก่า แต่ควรกล่าวถึงว่าใน Angular 1.4 $ httpParamSerializer ถูกเพิ่มเข้ามาและเมื่อใช้ $ http.post หากเราใช้ $ httpParamSerializer (params) เพื่อส่งผ่านพารามิเตอร์ทุกอย่างจะทำงานเหมือนคำขอโพสต์ทั่วไปและไม่มีการ deserializing JSON จำเป็นในฝั่งเซิร์ฟเวอร์

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


1

ฉันใช้เวลาหลายชั่วโมงในการทำความเข้าใจในขณะที่ทำงานกับ Angular และ PHP ข้อมูลโพสต์ไม่ไปที่ PHP ใน $ _POST

ในโค้ด PHP ให้ทำดังต่อไปนี้ - สร้างตัวแปร $ angular_post_params - จากนั้นทำดังต่อไปนี้ $angular_http_params = (array)json_decode(trim(file_get_contents('php://input')));

ตอนนี้คุณสามารถเข้าถึงพารามิเตอร์ของคุณได้เช่นเดียวกับที่คุณทำจาก $ _POST

$angular_http_params["key"]

ในกรณีที่คุณสงสัยเกี่ยวกับจาวาสคริปต์ .... นี่คือสิ่งที่ฉันใช้

    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 ลงในคอนเทนเนอร์ผู้ถือเนื้อหาของคุณในหน้า :)
Talha

.successและ.errorวิธีการเลิกใช้แล้วและได้ถูกลบออกจากกรอบ AngularJS
georgeawg
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.