AngularJS HTTP memposting ke PHP dan tidak ditentukan

107

Saya memiliki formulir dengan tag ng-submit="login()

Fungsi ini dipanggil dengan baik dalam javascript.

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

    $scope.email    = "[email protected]";
    $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');
        });
    }
}

Saya mendapatkan respons 200 OK kembali dari file PHP, namun, data yang dikembalikan mengatakan itu emaildan passwordtidak ditentukan. Ini semua php yang saya miliki

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

Adakah ide mengapa saya mendapatkan POSTnilai yang tidak terdefinisi ?

EDIT

Saya ingin menunjukkan karena ini sepertinya pertanyaan yang populer (namun sudah lama), .successdan .errorsudah usang dan Anda harus menggunakan .thenseperti yang ditunjukkan @James Gentes di komentar

Ronnie
sumber
2
Apakah Anda melihat tab jaringan alat pengembang Anda? Nilai apa yang diteruskan $http?
Marcel Korpel
1
Di tab jaringan, di Form-Databawahnya tertulis{"email":"[email protected]","password":"1234"}
Ronnie
@Ronnie Sepertinya JSON. Coba print_r($_POST);dan kemudian coba json_decode()pada indeks yang benar
HamZa
1
echo 'test';bekerja dengan baik. Saya pasti menunjuk ke file yang benar
Ronnie
1
Perhatikan bahwa .success dan .error tidak digunakan lagi dan diganti dengan .then ( docs.angularjs.org/api/ng/service/$http )
James Gentes

Jawaban:

228

angularjs .post()default header tipe konten ke application/json. Anda menimpa ini untuk meneruskan data yang dikodekan formulir, namun Anda tidak mengubah datanilai Anda untuk meneruskan string kueri yang sesuai, sehingga PHP tidak terisi $_POSTseperti yang Anda harapkan.

Saran saya adalah dengan hanya menggunakan pengaturan default angularjs application/jsonsebagai header, membaca input mentah di PHP, dan kemudian deserialize JSON.

Itu bisa dicapai dalam PHP seperti ini:

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

Bergantian, jika Anda sangat bergantung pada $_POSTfungsionalitas, Anda bisa membentuk string kueri seperti [email protected]&password=somepassworddan mengirimkannya sebagai data. Pastikan string kueri ini dikodekan URL. Jika dibuat secara manual (sebagai lawan menggunakan sesuatu seperti jQuery.serialize()), Javascript encodeURIComponent()harus melakukan trik untuk Anda.

Mike Brant
sumber
7
Tidak meremehkan pengetahuan Anda, tetapi menggunakan file_get_contents("php://input");sepertinya semacam retasan, bukan? Saya belum pernah mendengar tentang ini. Apa yang perlu terjadi jadi saya bisa mereferensikannya seperti$_POST['email'];
Ronnie
6
@Ronnie Ini bukan hack. Ini sangat tergantung pada bagaimana Anda ingin mengatur layanan web Anda. Jika Anda ingin mengirim dan mengambil JSON, Anda perlu bekerja dengan input mentah karena $_POSTtidak akan diisi.
Mike Brant
1
@lepe Tidak jelas bagi saya bagaimana pertanyaan / jawaban terkait terkait dengan jawaban saya. Tidak ada diskusi tentang perlunya membuat serial objek javascript di sini.
Mike Brant
2
@lascort sebenarnya tidak banyak perbedaan dengan solusinya. Dalam solusi saya, saya tidak mengisi data ke $ _POST, lebih memilih variabel yang ditentukan pengguna. Secara umum, ini lebih masuk akal bagi saya karena ketika bekerja dengan data serial JSON, Anda mungkin bekerja dengan objek, atau array yang diindeks secara numerik. Saya tidak akan menyarankan menambahkan array yang diindeks secara numerik ke $ _POST, karena ini akan menjadi penggunaan yang tidak biasa. Saya juga biasanya enggan memasukkan data ke salah satu superglobals yang digunakan untuk memasukkan data.
Mike Brant
1
@ItsmeJulian belum ada jawaban mutlak yang benar. Ini mungkin sangat bergantung pada bagaimana aplikasi Anda dirancang. Jika Anda berinteraksi dengan layanan REST yang menggunakan / mengirimkan JSON, maka saya mungkin akan tetap menggunakan tipe konten JSON. Jika saya bekerja sebagian besar dengan titik akhir yang dapat menghasilkan fragmen HTML atau HTML atau menggunakan posting formulir dasar sebagai fallback ke AJAX, maka saya mungkin cenderung untuk tetap menggunakan pengkodean formulir.
Mike Brant
41

Saya melakukannya di sisi server, pada awal file init saya, berfungsi seperti pesona dan Anda tidak perlu melakukan apa pun dalam kode php bersudut atau yang sudah ada:

if ($_SERVER['REQUEST_METHOD'] == 'POST' && empty($_POST))
    $_POST = json_decode(file_get_contents('php://input'), true);
valmarv
sumber
3
Anda harus membuang hasil Anda dalam kasus $ _POST kosong: $_POST = (array) json_decode(file_get_contents('php://input'), true).
M'sieur Toph '12
Saya tidak begitu mengerti mengapa orang-orang PHP tidak menerapkan ini sendiri, Mereka benar-benar mengharapkan posting yang disandikan url selalu ??
azerafati
@Bludream Saya tidak mengerti mengapa ada orang yang mengharapkan PHP melakukan apa yang diharapkan. Itu melanggar prinsip paling tidak mengejutkan sepanjang waktu.
doug65536
Ini sepertinya pendekatan yang sangat rapuh kecuali Anda benar-benar tahu bahwa data yang diposkan mewakili larik asosiatif (representasi objek dalam JSON). Bagaimana jika JSON berisi representasi larik yang diindeks secara numerik? $_POSTpada akhirnya akan mendapatkan array yang diindeks secara numerik dalam kasus ini, sesuatu yang akan menjadi perilaku yang sangat tidak terduga di bagian lain dari sistem yang mengandalkan $_POSTperilaku superglobal yang konsisten .
Mike Brant
1
Saya hanya menggunakan ini dalam aplikasi bertenaga sudut, tentu saja, dan saya memvalidasi data POST saya dengan sangat teliti, tidak melihat bagaimana ini bisa menjadi masalah ...
valmarv
14

Dalam API yang saya kembangkan, saya memiliki pengontrol dasar dan di dalam metode __construct () saya memiliki yang berikut ini:

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

Hal ini memungkinkan saya untuk mereferensikan data json sebagai $ _POST ["var"] saat diperlukan. Bekerja dengan baik.

Dengan cara itu jika pengguna yang diautentikasi terhubung dengan pustaka seperti jQuery yang mengirimkan data posting dengan default Jenis Konten: application / x-www-form-urlencoded atau Jenis Konten: application / json, API akan merespons tanpa kesalahan dan akan buat API sedikit lebih ramah pengembang.

Semoga ini membantu.

Tim Wickstrom
sumber
11

Karena PHP tidak secara asli menerima JSON, 'application/json'satu pendekatan adalah memperbarui header dan parameter Anda dari sudut sehingga api Anda dapat menggunakan data secara langsung.

Pertama , Parameterkan data Anda:

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

Kemudian , tambahkan yang berikut ini ke file$http

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

Jika semua permintaan Anda mengarah ke PHP, parameternya dapat disetel secara global dalam konfigurasi sebagai berikut:

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

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

        }]);

Kode Sisi Server: -

<?php


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

?>

Karena perilaku sudut tidak ada metode langsung untuk perilaku posting normal di server PHP, jadi Anda harus mengelolanya di objek json.

Rajendra Khabiya
sumber
1
Ini salah Lihat jawaban di atas di mana JSON dibaca langsung dari input mentah PHP. Ini jauh lebih mudah daripada mencampurkan JSON ke dalam string kueri.
Mike Brant
Metode .successdan .errortidak digunakan lagi dan telah dihapus dari kerangka kerja AngularJS.
georgeawg
6

Anda perlu melakukan deserialisasi data formulir Anda sebelum meneruskannya sebagai parameter kedua ke .post (). Anda dapat mencapai ini menggunakan metode $ .param (data) jQuery. Kemudian Anda akan dapat di sisi server untuk mereferensikannya seperti $ .POST ['email'];

bahramzy.dll
sumber
6

Ini adalah solusi terbaik (IMO) karena tidak memerlukan jQuery dan tidak ada decode JSON:

Sumber: https://wordpress.stackexchange.com/a/179373 dan: https://stackoverflow.com/a/1714899/196507

Ringkasan:

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

Contoh:

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

Kode PHP:

<?php
    $id = $_POST["id"];
?>
lepe
sumber
Bagaimana dengan: JSON.stringify('{ id: 'some_id', name : 'some_name' }')atau $httpParamSerializeruntuk konversi sisi klien?
qrtLs
5

Ini adalah pertanyaan lama tetapi perlu disebutkan bahwa di Angular 1.4 $ httpParamSerializer ditambahkan dan saat menggunakan $ http.post, jika kita menggunakan $ httpParamSerializer (params) untuk meneruskan parameter, semuanya berfungsi seperti permintaan posting biasa dan tidak ada deserialisasi JSON dibutuhkan di sisi server.

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

Sep
sumber
1

Butuh waktu berjam-jam untuk memahami hal itu saat bekerja dengan Angular dan PHP. Data posting tidak akan PHP di $ _POST

dalam kode PHP lakukan hal berikut. - Buat variabel $ angular_post_params - Kemudian lakukan hal berikut $angular_http_params = (array)json_decode(trim(file_get_contents('php://input')));

sekarang Anda dapat mengakses parameter Anda seperti yang Anda lakukan dari $ _POST

$angular_http_params["key"]

jika Anda bertanya-tanya tentang javascript .... inilah yang saya gunakan

    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");
        });
    });
Talha
sumber
untuk pemula ... jangan lupa untuk menambahkan arahan ng-app dan ng-controller ke wadah pemegang konten Anda di halaman :)
Talha
Metode .successdan .errortidak digunakan lagi dan telah dihapus dari kerangka kerja AngularJS.
georgeawg