PHPへのAngularJS HTTPポストおよび未定義


107

タグ付きのフォームがあります 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応答が返されますが、返されたデータはそれを示してemailおりpassword、未定義です。これは私が持っているすべてのphpです

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

なぜ未定義のPOST値を取得しているのですか?

編集

私は、これは(まだそれが古いです)人気の質問のようですので、指摘したかった、.success.error推奨されていません、あなたが使用する必要があります.then@James gensの複数形はcommmentsで指摘したように


2
開発者ツールのネットワークタブを見ましたか?渡される値は何$httpですか?
Marcel Korpel 2013年

1
ネットワークタブでは、その下Form-Dataに次のように表示されます{"email":"fsdg@sdf.com","password":"1234"}
ロニー

@RonnieはJSONのようです。正しいインデックスでprint_r($_POST);試しjson_decode()てみてください
HamZa 2013年

1
echo 'test';正常に動作します。私は確かに正しいファイルを指しています
Ronnie

1
.successと.errorは非推奨になり、.then(docs.angularjs.org/api/ng/service/$http)に置き換えられました
James Gentes

回答:


228

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&password=somepasswordし、それをデータとして送信できます。このクエリ文字列がURLエンコードされていることを確認してください。のようなものを使用するのではなく、手動で作成した場合はjQuery.serialize()、JavaScript encodeURIComponent()でうまくいくはずです。


7
あなたの知識を軽視していませんが、使用file_get_contents("php://input");は一種のハックのように思われますか?私はこれについて聞いたことがありません。私がちょうどそれを参照できるようにするために何が起こる必要があるか$_POST['email'];
ロニー

6
@ロニーそれはハックではありません。これは、実際にWebサービスをどのようにセットアップするかによって異なります。JSONを送信および取得する場合は、データが入力され$_POSTないため、未加工の入力を処理する必要があります。
マイクブラント

1
@lepeリンクされた質問/回答が私の回答とどのように関連しているかは、はっきりしません。ここでは、javascriptオブジェクトをシリアル化する必要があることについての説明はありません。
マイクブラント

2
@lascortソリューションとの違いはほとんどありません。私のソリューションでは、データを$ _POSTに入力せず、代わりにユーザー定義変数を使用します。一般に、これは、JSONシリアル化されたデータを操作するときに、オブジェクトまたは数値でインデックス付けされた配列を操作する可能性があるという点で、私にとってより理にかなっています。$ _POSTに数値でインデックス付けされた配列を追加することはお勧めしません。これは典型的な使用法ではないためです。また、私は通常、入力データに使用されるスーパーグローバルにデータを入力することを避けます。
マイクブラント2016年

1
@ItsmeJulian絶対的な正解はありません。実際のアプリケーションの設計方法に依存する場合があります。JSONを使用/配信しているRESTサービスとやり取りしている場合は、おそらくJSONコンテンツタイプを使用します。HTMLまたはHTMLフラグメントを生成できるエンドポイントを主に使用しているか、AJAXへのフォールバックとして基本的なフォーム投稿を使用している場合、フォームエンコーディングを使用する傾向があります。
マイクブラント2017年

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 '2014

PHPの連中が自分で実装しなかった理由はわかりません。URLエンコードされた投稿を常に期待していますか?
azerafati 2015

@Bludream誰もがPHPが期待されていることをすることを期待する理由がわかりません。それは常に最小サプライズの原則に違反しています。
doug65536 2015

これは、POSTされたデータが連想配列(JSONでのオブジェクト表現)を表すことを絶対に知らない限り、非常に壊れやすいアプローチのようです。JSONに数値でインデックス付けされた配列表現が含まれていた場合はどうなりますか? $_POSTこの場合、数値でインデックスが付けられた配列を取得することになり$_POSTます。これは、一貫したスーパーグローバル動作に依存するシステムの他の部分では非常に予期しない動作になるものです。
マイクブラント

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"]として簡単に参照できます。よく働く。

そうすれば、認証されたユーザーが、デフォルトのContent-Type:application / x-www-form-urlencodedまたはContent-Type:application / jsonで投稿データを送信するjQueryなどのライブラリに接続した場合、APIはエラーなしで応答し、 APIを開発者にやさしいものにします。

お役に立てれば。


11

PHPはJSONをネイティブに受け入れないため'application/json'、APIがデータを直接使用できるように、ヘッダーとパラメーターをAngularから更新する方法があります。

まず、データをパラメーター化します。

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のraw入力から直接読み取られる上記の回答を参照してください。これは、JSONをクエリ文字列に混在させるよりもはるかに簡単です。
マイクブラント2016年

メソッドは廃止され、AngularJSフレームワークから削除されました。.success.error
georgeawg

6

.post()の2番目のパラメーターとして渡す前に、フォームデータを逆シリアル化する必要があります。これは、jQueryの$ .param(データ)メソッドを使用して実現できます。その後、サーバー側で$ .POST ['email']のように参照できます。


6

jQueryもJSONデコードも必要ないため、これが最良のソリューション(IMO)です。

ソース: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 2016

5

これは古い質問ですが、Angular 1.4では$ httpParamSerializerが追加され、$ http.postを使用するときに$ httpParamSerializer(params)を使用してパラメーターを渡すと、すべてが通常のpostリクエストのように機能し、JSONのデシリアライズは行われません。サーバー側で必要。

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


1

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ディレクティブを追加することを忘れないでください:)
Talha

メソッドは廃止され、AngularJSフレームワークから削除されました。.success.error
georgeawg
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.