使用 Angular $http 服务获取 PHP AJAX 响应数据

Getting PHP AJAX response data with Angular $http Service

如果这是重复之前的问题,我很抱歉,但我一直无法找到似乎可以解决我的问题的解决方案并且我是 Angular 的新手。

我有一个 Angular 表单,它与 PHP 通信数据以发送电子邮件,我的问题是处理来自 PHP 的 JSON 响应(因为 PHP 回传它是否在 JSON 本身内成功,连同一条消息)。 我似乎无法让代码根据 JSON 中包含的 "success" 值进行响应,也无法实际显示“消息。

JSON 响应数据如下所示(由于电子邮件问题而失败时):

所以我的angular代码需要根据"success"是真还是假来响应,同时还要显示AJAX在[=40中传递的"message" =].

我的Angular控制器代码:

app.controller('ContactController', function ($scope, $http) {
    $scope.result = 'hidden'
    $scope.resultMessage;
    $scope.formData; //formData is an object holding the name, email, subject, and message
    $scope.submitButtonDisabled = false;
    $scope.submitted = false; 
    $scope.submit = function(contactform) {
        $scope.submitted = true;
        $scope.submitButtonDisabled = true;
        if (contactform.$valid) {
            var request = $http({
                method  : 'POST',
                url     : 'php/contact.php',
                data    : $.param($scope.formData),  //param method from jQuery
                headers : { 'Content-Type': 'application/x-www-form-urlencoded' } 
            });
            if (request.success) { 
                console.log(request);
                $scope.submitButtonDisabled = false;
                $scope.result='bg-success';
                $scope.resultMessage = request.message;
              } else {
                $scope.submitButtonDisabled = true;
                $scope.resultMessage = request.message;
                //$scope.resultMessage = "Opps!... something went wrong.  Please Contact OpenHouse directly to let them know of this error.";
                $scope.result='bg-danger';
            };
               //};
           } else {
            $scope.submitButtonDisabled = false;
            $scope.resultMessage = 'Failed <img src="http://www.chaosm.net/blog/wp-includes/images/smilies/icon_sad.gif" alt=":(" class="wp-smiley">  Please fill out all the fields.';
            $scope.result='bg-danger';
        }
    }
});

我的PHP代码:

<?php

  require_once ("class.phpmailer.php");   // Include phpmailer class
  ini_set('display_errors', 'On');
  error_reporting(E_ALL | E_STRICT);

  if (isset($_POST['inputFirstName']) && isset($_POST['inputLastName']) && isset($_POST['inputEmail']) && isset($_POST['inputPhone']) && isset($_POST['inputMessage'])) {

    //check if any of the inputs are empty
    if (empty($_POST['inputFirstName']) || empty($_POST['inputLastName']) || empty($_POST['inputEmail']) || empty($_POST['inputPhone']) || empty($_POST['inputMessage'])) {
        $data = array('success' => false, 'message' => 'Please fill out the form completely.');
        echo json_encode($data);
        exit;
    }

    $message=
    'First Name:    '.$_POST['inputFirstName'].'<br />
    Last Name:  '.$_POST['inputLastName'].'<br />
    Phone:  '.$_POST['inputPhone'].'<br />
    Email:  '.$_POST['inputEmail'].'<br />
    Comments:   '.$_POST['inputMessage'].'
    ';

    $mail = new PHPMailer();        // Instantiate the PHPMailer Class
    $mail->IsSMTP();                // enable SMTP
    $mail->SMTPDebug = 1;           // debugging: 1 = errors and messages, 2 = messages only
    $mail->SMTPAuth = true;         // SMTP authentication enabled
    $mail->SMTPSecure = 'ssl';      // secure transfer enabled + REQUIRED for Gmail (either SSL or TLS)
    $mail->Host = "smtp.gmail.com"; //Gmail SMTP Server to relay thru
    $mail->Port = 465; // Port 465 as we're using SSL... or use Port 587 for TLS
    $mail->IsHTML(true);                               // We're sending a HTML formatted message
    $mail->Username = "....@gmail.com"; // Gmail account for authentication
    $mail->Password = "*********";                     // Gmail password for authentication
    $mail->SetFrom("....@gmail.com");   // The email is being sent from this address
    $mail->Subject = "Website Contact Form Enquiry";   // The subject line of the email
    $mail->Body = ($message);                          // The actual email message to be sent
    $mail->AddAddress("....@gmail.com"); // The email is being sent to this address

   if(!$mail->send()) {
     echo json_encode(['success' => false, 'message' => 'Message could not be sent. Mailer Error: ' . $mail->ErrorInfo]);
     exit;
   }

   error_log("Data: ".$data['success']." Message: ".$data['message']);
   echo json_encode(['success' => true, 'message' => 'Thanks! We have received your message.']);

    } else {
      echo json_encode(['success' => false, 'message' => 'Please fill out the form completely.']);
    }
 ?>

首先,$http 不是 return 一个 request 对象,它 return 是一个用 response 对象解析的承诺:

        //var request = $http({
        //It returns a promise
        var promise = $http({
            method  : 'POST',
            url     : 'php/contact.php',
            data    : $.param($scope.formData),  //param method from jQuery
            headers : { 'Content-Type': 'application/x-www-form-urlencoded' } 
        });
        //Use .then method to receive response
        promise.then(function (response) {
          var request = response.data; 
          if (request.success) {
            console.log(request);
            $scope.submitButtonDisabled = false;
            $scope.result='bg-success';
            $scope.resultMessage = request.message;
          }
        });

重要的是要意识到 $http 服务立即 return 是一个 待处理的 承诺。当响应从服务器返回时,承诺 稍后 得到解决(实现或拒绝)。

使用 promise 的 .then 方法提供成功和拒绝处理程序,这些处理程序通过已完成或已拒绝的响应进行解析。

有关详细信息,请参阅:AngularJS $http Service API Reference - General Usage


更新

AngularJS 框架默认使用 Content-Type: 'application/json' 进行编码和发布。

要在 PHP 后端接收 JSON 数据,请执行以下操作:

$json = file_get_contents('php://input');
$obj = json_decode($json);

那么POST和AngularJS可以简化为:

    var promise = $http({
        method  : 'POST',
        url     : 'php/contact.php',
        //data    : $.param($scope.formData),  //param method from jQuery
        data: $scope.data;
        //headers : { 'Content-Type': 'application/x-www-form-urlencoded' }
        //Defaults to:
        //headers: {'Content-Type': 'application/json'} 
    });
    //Use .then method to receive response
    promise.then(function (response) {
      var request = response.data; 
      if (request.success) {
        console.log(request);
        $scope.submitButtonDisabled = false;
        $scope.result='bg-success';
        $scope.resultMessage = request.message;
      }
    });

感谢大家的帮助; 我能够在异步 http 调用后 return 响应并将其显示在屏幕上...... 但无论我尝试什么,它总是在数据响应中将 HTTP headers 与数据打包在一起。

如果 PHP 没有发送电子邮件(我删除了所有发送电子邮件的命令),那么数据响应将只是数据。 如果 PHP 确实发送了电子邮件,则响应将是 HTTP headers + 数据响应中的数据。

所以最后在 Angular 端,我将数据响应转换为一个字符串,根据 { 拆分该字符串,这将给我一个仅包含数据的新字符串(和没有 headers),一些额外的 \ 分隔字符串中的值,并且显然以 }

结尾

因此,通过字符串操作,我能够得到我想要的响应。

这是正在工作的 Angular 控制器:

app.controller('ContactController', function ($scope, $http) {
    $scope.result = 'hidden'
    $scope.resultMessage;
    $scope.formData; //formData is an object holding the name, email, subject, and message
    $scope.submitButtonDisabled = false;
    $scope.submitted = false;
    $scope.submit = function(contactform) {
        $scope.submitted = true;
        $scope.submitButtonDisabled = true;
            var promise = $http({
                method  : 'POST',
                url     : 'php/contact.php',
                data    : {
                    firstname: $scope.formData.inputFirstName,
                    lastname: $scope.formData.inputLastName,
                    emailid: $scope.formData.inputEmail,
                    phoneno: $scope.formData.inputPhone,
                    message: $scope.formData.inputMessage
                },
                headers : {'Content-Type': 'application/json'}
            })
            promise.then(function (response) {
              var request = JSON.stringify(response.data);  //convert JSON data to string for manipulation
              var startpos = request.indexOf("{");          //locate '{' as its the start of the data we want
              var endpos = request.lastIndexOf("}");        //locate '}' as its the end of the data we want
              var res = request.slice(startpos, endpos);    //Extract the actual data now we know where it is.
              var newresponse = res.split("\");            //Split the data into new array
              var answer = request.search("true");          //search the string to see if it contains the word "true" meaning an email was sent.

              if (answer >= 0) {
                $scope.submitButtonDisabled = false;
                $scope.result='bg-success';
                $scope.resultMessage = newresponse[5].replace('"', " ");
              } else {
                $scope.submitButtonDisabled = true;
                $scope.resultMessage = newresponse[5].replace('"', " ");
                $scope.result='bg-danger';
              }
          });
        }
    });