AngularJS HTTP-Post an PHP und undefiniert


107

Ich habe ein Formular mit dem Tag ng-submit="login()

Die Funktion wird in Javascript als fein bezeichnet.

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

Ich erhalte eine 200-OK-Antwort von der PHP-Datei zurück, die zurückgegebenen Daten sagen dies jedoch emailund passwordsind undefiniert. Das ist alles was ich habe

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

Irgendeine Idee, warum ich undefinierte POSTWerte erhalte ?

BEARBEITEN

Ich wollte darauf hinweisen, da dies eine beliebte Frage zu sein scheint (aber es ist alt) .successund .errorveraltet ist und Sie verwenden sollten, .thenwie @James Gentes in den Kommentaren hervorhob


2
Haben Sie sich die Registerkarte "Netzwerk" Ihrer Entwicklertools angesehen? Welcher Wert wird übergeben $http?
— Marcel Korpel

1
In der Registerkarte Netzwerk unter Form-Dataes sagt{"email":"fsdg@sdf.com","password":"1234"}
— Ronnie

@ Ronnie Scheint wie JSON. Versuchen Sie print_r($_POST);und dann versuchen Sie json_decode()auf dem richtigen Index
— HamZa

1
echo 'test';funktioniert gut. Ich zeige auf jeden Fall auf die richtige Datei
— Ronnie

1
Beachten Sie, dass .success und .error veraltet sind und durch .then ( docs.angularjs.org/api/ng/service/$http ) ersetzt wurden
— James Gentes

Antworten:


228

angularjs verwendet .post()standardmäßig den Header für den Inhaltstyp application/json. Sie überschreiben dies, um formularcodierte Daten zu übergeben. Sie ändern jedoch nicht Ihren dataWert, um eine geeignete Abfragezeichenfolge zu übergeben, sodass PHP nicht $_POSTwie erwartet ausgefüllt wird.

Mein Vorschlag wäre, einfach die Standardeinstellung anglejs von application/jsonals Header zu verwenden, die Roheingabe in PHP zu lesen und dann den JSON zu deserialisieren.

Das kann in PHP so erreicht werden:

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

Wenn Sie sich stark auf $_POSTFunktionalität verlassen, können Sie alternativ eine Abfragezeichenfolge wie diese bilden email=someemail@email.com&password=somepasswordund diese als Daten senden. Stellen Sie sicher, dass diese Abfragezeichenfolge URL-codiert ist. Wenn jQuery.serialize()Javascript manuell erstellt wird (im Gegensatz zur Verwendung von etwas Ähnlichem ), encodeURIComponent()sollte es den Trick für Sie tun.


7
Ihr Wissen nicht zu missachten, aber zu verwenden file_get_contents("php://input");scheint eine Art Hack zu sein, nicht wahr? Ich habe noch nie davon gehört. Was muss passieren, damit ich es einfach so referenzieren kann$_POST['email'];
— Ronnie

6
@ Ronnie Es ist kein Hack. Es hängt wirklich davon ab, wie Sie Ihren Webdienst einrichten möchten. Wenn Sie JSON senden und abrufen möchten, müssen Sie mit Roheingaben arbeiten, $_POSTdie nicht ausgefüllt werden.
— Mike Brant

1
@lepe Es ist mir nicht klar, wie sich die verknüpfte Frage / Antwort auf meine Antwort bezieht. Es gibt hier keine Diskussion darüber, ein Javascript-Objekt serialisieren zu müssen.
— Mike Brant

2
@lascort gibt es wirklich keinen großen Unterschied zu den Lösungen wirklich. In meiner Lösung fülle ich die Daten nicht in $ _POST, sondern bevorzuge stattdessen eine benutzerdefinierte Variable. Im Allgemeinen ist dies für mich insofern sinnvoller, als Sie bei der Arbeit mit JSON-serialisierten Daten möglicherweise mit Objekten oder numerisch indizierten Arrays arbeiten. Ich würde nicht vorschlagen, $ _POST ein numerisch indiziertes Array hinzuzufügen, da dies eine atypische Verwendung wäre. Ich scheue mich im Allgemeinen auch davor, Daten in die Superglobalen zu schreiben, die für Eingabedaten verwendet werden.
— Mike Brant

1
@ItsmeJulian gibt es keine absolut richtige Antwort. Es kann wirklich davon abhängen, wie Ihre Anwendung aufgebaut ist. Wenn Sie mit einem REST-Service interagieren, der JSON verbraucht / bereitstellt, würde ich mich wahrscheinlich an den JSON-Inhaltstyp halten. Wenn ich größtenteils mit einem Endpunkt gearbeitet habe, der HTML- oder HTML-Fragmente erzeugen kann oder die einfache Formularveröffentlichung als Fallback für AJAX verwendet, bin ich möglicherweise geneigt, mich an die Formularcodierung zu halten.
— Mike Brant

41

Ich mache es auf der Serverseite, am Anfang meiner Init-Datei, funktioniert wie ein Zauber und Sie müssen nichts in eckigem oder vorhandenem PHP-Code tun:

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

3
Sie sollten Ihr Ergebnis umwandeln, falls $ _POST leer ist : $_POST = (array) json_decode(file_get_contents('php://input'), true).
— M'sieur Toph '12.

Ich verstehe nicht wirklich, warum PHP-Leute dies nicht selbst implementiert haben. Sie erwarten wirklich immer URL-codierte Posts?
— Azerafati

@Bludream Ich verstehe nicht, warum jemand erwartet, dass PHP das tut, was erwartet wird. Es verstößt ständig gegen das Prinzip der geringsten Überraschung.
— Doug65536

Dies scheint ein sehr fragiler Ansatz zu sein, es sei denn, Sie wissen absolut, dass die POST-Daten ein assoziatives Array darstellen (eine Objektdarstellung in JSON). Was ist, wenn der JSON eine numerisch indizierte Array-Darstellung enthält? $_POSTwürde in diesen Fällen ein numerisch indiziertes Array erhalten, was in anderen Teilen des Systems, die auf einem konsistenten $_POSTsuperglobalen Verhalten beruhen, ein sehr unerwartetes Verhalten wäre.
— Mike Brant

1
Ich benutze dies natürlich nur in Anwendungen mit Winkelantrieb und validiere meine POST-Daten sehr gründlich. Ich sehe nicht, wie das ein Problem sein kann ...
— Valmarv

14

In der API, die ich entwickle, habe ich einen Basis-Controller und in seiner __construct () -Methode habe ich Folgendes:

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

Dadurch kann ich die JSON-Daten bei Bedarf einfach als $ _POST ["var"] referenzieren. Funktioniert super.

Auf diese Weise antwortet die API fehlerfrei und reagiert, wenn sich ein authentifizierter Benutzer mit einer Bibliothek wie einer jQuery verbindet, die Post-Daten mit dem Standardwert Inhaltstyp: application / x-www-form-urlencoded oder Inhaltstyp: application / json sendet Machen Sie die API etwas entwicklerfreundlicher.

Hoffe das hilft.


11

Da PHP JSON nicht nativ akzeptiert 'application/json'Ein Ansatz besteht darin, Ihre Header und Parameter aus dem Winkel zu aktualisieren, damit Ihre API die Daten direkt verwenden kann.

Erstens , Parametrieren Ihre Daten:

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

Fügen Sie dann Folgendes zu Ihrem hinzu$http

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

Wenn alle Ihre Anforderungen an PHP gehen, können die Parameter in der Konfiguration wie folgt global festgelegt werden:

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

8

Angular Js Demo Code: -

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

        }]);

Serverseitiger Code: -

<?php


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

?>

Aufgrund des Winkelverhaltens gibt es keine direkte Methode für das normale Post-Verhalten auf dem PHP-Server. Sie müssen es daher in JSON-Objekten verwalten.


1
Das ist falsch. Siehe die obigen Antworten, in denen JSON direkt von der PHP-Roheingabe gelesen wird. Dies ist viel einfacher als das Mischen von JSON in eine Abfragezeichenfolge.
— Mike Brant

Die Methoden .successund .errorsind veraltet und wurden aus dem AngularJS-Framework entfernt.
— Georgeawg

6

Sie müssen Ihre Formulardaten deserialisieren, bevor Sie sie als zweiten Parameter an .post () übergeben. Sie können dies mit der $ .param (data) -Methode von jQuery erreichen. Dann können Sie auf der Serverseite darauf verweisen, wie $ .POST ['email'];


6

Dies ist die beste Lösung (IMO), da keine jQuery und keine JSON-Dekodierung erforderlich sind:

Quelle: https://wordpress.stackexchange.com/a/179373 und: https://stackoverflow.com/a/1714899/196507

Zusammenfassung:

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

Beispiel:

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

PHP-Code:

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

Was ist mit: JSON.stringify('{ id: 'some_id', name : 'some_name' }')oder $httpParamSerializerfür die clientseitige Konvertierung?
— qrtLs

5

Es ist eine alte Frage, aber es ist erwähnenswert, dass in Angular 1.4 $ httpParamSerializer hinzugefügt wird. Wenn Sie $ http.post verwenden und $ httpParamSerializer (params) verwenden, um die Parameter zu übergeben, funktioniert alles wie eine reguläre Post-Anfrage und keine JSON-Deserialisierung auf der Serverseite benötigt.

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


1

Ich habe Stunden gebraucht, um das zu verstehen, während ich mit Angular und PHP gearbeitet habe. Post-Daten gingen in $ _POST nicht an PHP

Gehen Sie im PHP-Code wie folgt vor. - Erstellen Sie eine Variable $ angle_post_params. - Führen Sie dann die folgenden Schritte aus $angular_http_params = (array)json_decode(trim(file_get_contents('php://input')));

Jetzt können Sie wie in $ _POST auf Ihre Parameter zugreifen

$angular_http_params["key"]

Für den Fall, dass Sie sich über Javascript wunderten ... das habe ich verwendet

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

für Neulinge ... vergessen Sie nicht, ng-app- und ng-controller-Direktiven zu Ihrem Inhaltsinhaber-Container auf der Seite hinzuzufügen :)
— Talha

Die Methoden .successund .errorsind veraltet und wurden aus dem AngularJS-Framework entfernt.
— Georgeawg
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.