jordan
jordan

Reputation: 3546

Why is my Angular POST request to a PHP page not setting up the POST array?

I have a angular post that sends to my php file, but in the PHP file, I cannot access anything from the post variable. It returns my SUCCESS string, but nothing after that, so my return on the post is "SUCCESS - - - - - " where the data should be between the dashes.

JSON/JS object:

DESCRIPTION: "123321"
LOCATION: "ab_calgary_eighth_ave_pl"
NAME: "123321"
QUANTITY: 123321
TYPE: "cycle"

Angular POST Code:

        $scope.insertNewInventoryItem = function()
        {
            if(typeof ($scope.newItem.LOCATION) == 'undefined')
                alert("LocationCannot Be Empty.  Please Select An Option From The Drop Down.");

            else if(typeof ($scope.newItem.TYPE) == 'undefined')
                alert("Type Cannot Be Empty.  Please Select An Option From The Drop Down.");

            else
            {
                $http.post("dataaccess/addnewinventory.php", $scope.newItem).then(onAddNewComplete, onAddNewError);
            }
        }

PHP Page attempting to find the posted values:

<?php
$con = mysqli_connect("localhost", "dbadminuser", "password", "database_demo_inventory");

// Check connection
if (mysqli_connect_errno())
{
    echo "FAIL - Failed to connect to MySQL: " . mysqli_connect_error();
}
else
{
    echo "SUCCESS - " . $HTTP_POST_VARS['newItem.NAME'] . " - " . $HTTP_POST_VARS['TYPE'] . " - " . $HTTP_POST_VARS["QUANTITY"] . " - " . $HTTP_POST_VARS . " - " . $_POST[0];
}

mysqli_close($con);
?>

Picture of the Request from GOOGLE developer tools: enter image description here

Picture of return data from the request (see PHP code for where SUCCESS is coming from): enter image description here

Why can I not access the post variables? Am I missing something here?

Upvotes: 2

Views: 1782

Answers (4)

Jette
Jette

Reputation: 2609

My backend is Apache22/PHP5.4. I've been banging my head against the wall on this issue for days. Just now, I finally cracked it.

Setting content-type to application/x-www-form-urlencoded didn't get the data into input:// or $_POST. Then I came across this thread: https://groups.google.com/forum/#!topic/angular/MBf8qvBpuVE

Not setting Content-Type will make the underlying XHR browser implementation add a correct header

The keys is to set content-type: false. This is my working code, and I don't even have to get the data from input:// it goes directly to $_POST.

var serialized = $httpParamSerializer($scope.formData);

return $http({
  method  : 'POST',
  url     : 'your-url-here',
  data    : serialized,
  headers : { 'Content-Type': false }
}).then(
  function(response) {
    return response;
  },
  //Network or server error
  function(data, status, headers,config,statusText) {
    console.log('AJAX failure: status='+status+', statusText='+statusText);
  } 
);

I am very new to AngularJS, and so I have no idea why setting the header didn't work for me.

Upvotes: 1

jordan
jordan

Reputation: 3546

For decoding the PHP, I used the following code, which gave me direct access into the POST data, which in my case was JSON. Apparently JSON is a unsupported data structure, so PHP failed to parse it automatically into the POST array:

$jsonText = file_get_contents('php://input');
$decodedText = html_entity_decode($jsonText);
$myArray = json_decode('[' . $decodedText . ']', true);

Explanation: Line 1 gets the raw data that was sent over from the request (in this case it was from the Angular Controller posted in the OP. Line 2 decodes the JSON array grabbed in step one, correctly forming it to parse later. Note that in this case, steps one and two both return the exact same looking object. Line 3 takes the formatted JSON data and decodes it into a PHP array. Now you can use the following to access parts of the array:

$myvar = $myArray[0]["SOME_VARIABLE"];

Thanks for the answers guys!

Upvotes: 0

code-jaff
code-jaff

Reputation: 9330

while chickenrice's answer is true and solves the issue, I'd prefer to use the JSON data as the payload at least for few reasons.

  • suits if your objects are complicated, contains nested structures.
  • It allows you to send any kind of object e.g. [[1,2],[3,4]] - Array(array,array..) This is just impossible to send in uri-encoded string.
  • It's not comfortable if you send simple "name=egor&type=lulzsec" since it will look "verbose".
  • You CAN omit CSRF tokens with this!

To get this in PHP make use of file_get_contents("php://input"); to get the request body directly. You would need to have a small wrapper around this. Moreover you might need to whitelist the content type headers to mitigate the CSRF.

EDIT

if (0 === strpos($_SERVER['CONTENT_TYPE'], 'application/json')) {
    $input_json = file_get_contents('php://input');
    $input= json_decode( $input_json, TRUE ); //convert JSON into array
}

Upvotes: 1

Chickenrice
Chickenrice

Reputation: 5727

By default, Angular transmits data using the Content-Type: "application/json" and PHP can't parse the JSON data into the $_POST natively. You could follow these two steps to resolve this issue:

Step 1: Change the default value of header Content-Type:

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

Step 2: Convert the JSON data into key=value pair serialized data. (I'm using jQuery $.param function to convert the data)

$http({
    method:"POST",
        url: "post.php",
        data: $.param($scope.newItem)
    }).success(function(data, status, headers, config){
        console.log(data);
    }).error(function(data, status, headers, config){
        console.log(status);
    });

Note: $HTTP_POST_VARS is not a super global variable and it has been completely deprecated in PHP 5. I think you could use $_POST.

Upvotes: 4

Related Questions