Sending an email with AngularJS and PHP?

2019-08-16 08:44发布

问题:

I've found a tutorial here about using the $http service to send data to PHP.

I think I understand the syntax for the submission in Angular, but I don't understand how he is getting the variables with $data = file_get_contents("php://input"); It seems like feeding file_get_contents a random URL?

Regardless, here is as far as I got. This is intended to send an email without a refresh. I'm not interested in returning anything right now, I just want to send the email.

HTML:

<script type="text/javascript" src="http://allenhundley.com/js/contact/contact.js"></script>
<div id="format">
    <div id="header">
    </div>
    <p id="text">
        Have any questions? Have a project? Shoot me an email here or at Allen@AllenHundley.com. 
    </p>
    <br />
    <input class="input" type="email" ng-model="email" placeholder="Email"/>
    <input class="input" type="text" ng-model="subject" placeholder="Subject"/>
    <textarea id="message" ng-model="message" placeholder="Message"></textarea>
    <button id="send" name="send" ng-click="emailCtrl.send()">Send Email</button>
</div>

AngularJS:

var emailController = spa.controller("emailController", ["$scope", "$http", function($scope, $http) {

    this.send = function() {

        $http.post('/php/send_email.php', {
            email : $scope.email,
            subject : $scope.subject,
            message : $scope.message
        });
    };
});

PHP:

<?php

    $user_email = $_POST["email"];
    $user_subject = $_POST["subject"];
    $user_message_input = $_POST["message"];

    $user_headers = 'MIME-Version: 1.0\r\n';
    $user_headers .= 'Content-type:text/html;charset=UTF-8\r\n';
    $user_headers .= 'From: <noReply@AllenHundley.com>\r\n';

    $user_message = "
        <html>
            <head>
                <title>
                    Thanks for contacting me!
                </title>
            </head>
            <body>
                " . $user_message_input . "
            </body>
        </html>
    ";

    mail($user_email, $user_subject, $user_message, $user_headers);

    $developer_to = "Allen@AllenHundley.com";
    $developer_subject = $user_subject;
    $developer_message = $user_message_input;

    $developer_headers = 'MIME-Version: 1.0\r\n';
    $developer_headers .= 'Content-type:text/html;charset=UTF-8\r\n';
    $developer_headers .= 'From: <' . $user_email . '>\r\n';

    $user_message = "
        <html>
            <head>
                <title>
                    Thanks for contacting me!
                </title>
            </head>
            <body>
                " . $developer_message . "
            </body>
        </html>
    ";

    mail($developer_to, $developer_subject, $developer_message, $developer_headers);

?>

I've tried to read the documentation on $http but I think I already have that part right. It doesn't say anything about PHP.

Where do I go from here?

回答1:

With the default Angular settings, you need to read the input from php://input because angular does not send the data in application/x-www-form-urlencoded format. It sends it to the server in application\json format.

You have two options:

  1. Set the headers option in Angular's $http function, like so:

$http({
  method: 'POST',
  url: '/php/send_email.php',
  headers: {'Content-Type': 'application/x-www-form-urlencoded'},
  data: {
    email : $scope.email,
    subject : $scope.subject,
    message : $scope.message
  }
});

  1. Use php://input instead of $_POST. You would do something like $post = json_decode(file_get_contents('php://input'));, and then you can do $user_email = $post['email']; and so on.

Update:

On second thought, there's a little more to option one than just changing the header. You also have to transform the data. This post has a good example of how to do that. It also shows you another option, which is to change the default content-type header and have this be the default behavior for your whole module.

Here is the function provided in that blog post to transform the data to a url-encoded string:

var param = function(obj) {
  var query = '', name, value, fullSubName, subName, subValue, innerObj, i;

  for(name in obj) {
    value = obj[name];

    if(value instanceof Array) {
      for(i=0; i<value.length; ++i) {
        subValue = value[i];
        fullSubName = name + '[' + i + ']';
        innerObj = {};
        innerObj[fullSubName] = subValue;
        query += param(innerObj) + '&';
      }
    }
    else if(value instanceof Object) {
      for(subName in value) {
        subValue = value[subName];
        fullSubName = name + '[' + subName + ']';
        innerObj = {};
        innerObj[fullSubName] = subValue;
        query += param(innerObj) + '&';
      }
    }
    else if(value !== undefined && value !== null)
      query += encodeURIComponent(name) + '=' + encodeURIComponent(value) + '&';
  }

  return query.length ? query.substr(0, query.length - 1) : query;
};

If you were to use this with the first option I listed above, you would simply pass the JS object to the params() function before assigning it to the data property:

data: params({
  email : $scope.email,
  subject : $scope.subject,
  message : $scope.message
})