Getting PHP AJAX response data with Angular $http Service - php

I'm sorry if this is repeating previous questions, but i haven't been able to find a solution which seems to work with my problem & im new to Angular.
I have an Angular form, which communicates data with PHP to send an email, and my problem is with handling the JSON response from the PHP (as the PHP communicates back whether it succeeded within the JSON itself, along with a message).
I can't seem to get the code to respond based on the "success" value contained within the JSON, nor actually display the "message.
The JSON response data looks like this (when it fails due to an email issue):
So my angular code needs to respond based on "success" being true or false, while also displaying the "message" which is passed by AJAX in JSON.
My Angular Controller code:
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';
}
}
});
My PHP Code:
<?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.']);
}
?>

To start, the $http does not return a request object, it returns a promise that resolves with a response object:
//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;
}
});
It is important to realize that the $http service immediately returns a pending promise. The promise is later resolved (either fulfilled or rejected) when the response comes back from the server.
Use the .then method of the promise to provide success and rejection handlers that resolve with either the fulfilled or rejected response.
For more information, see: AngularJS $http Service API Reference - General Usage
UPDATE
The AngularJS framework by default encodes and posts using Content-Type: 'application/json'.
To receive JSON data in a PHP backend, do something like:
$json = file_get_contents('php://input');
$obj = json_decode($json);
Then the POST with AngularJS can be simplified:
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;
}
});

Thanks everyone for the help;
I was able to return a response after the asyn http call & display it on the screen...
But no matter what i tried, it always packages the HTTP headers with the data, within the data response.
If the PHP didn't send an email (I removed all commands for sending email), then the data response would be just data.
If the PHP did send an email, then the response would be HTTP headers + data within the data response.
So in the end on the Angular side, i converted the data response to a string, split that string based up { which would give me a new string with just the data (and no headers), some extra \separating the values in the string, and obviously and ending }
So thus, by string manipulation, i was able to get the response i wanted.
Here's the working Angular Controller:
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';
}
});
}
});

Related

Add additional data to request object after initialisation

The below public function returns oauth token against user name and password. However, I have a requirement where, the username has to queried first from email id. In the first part of the function, I need to somehow add the username to the request object. The request is created using laminas from what I can understand.
Full code from which function is taken is here.
/**
* Processes POST requests to /oauth/token.
*/
public function token(ServerRequestInterface $request) {
////////////////
////////////////
// ADD LOGIC TO GET EMAIL FROM REQUEST & GET USERNAME
// ADD USERNAME TO $request
////////////////
////////////////
//Extract the grant type from the request body.
$body = $request->getParsedBody();
$grant_type_id = !empty($body['grant_type']) ? $body['grant_type'] : 'implicit';
$client_drupal_entity = NULL;
if (!empty($body['client_id'])) {
$consumer_storage = $this->entityTypeManager()->getStorage('consumer');
$client_drupal_entities = $consumer_storage
->loadByProperties([
'uuid' => $body['client_id'],
]);
if (empty($client_drupal_entities)) {
return OAuthServerException::invalidClient($request)
->generateHttpResponse(new Response());
}
$client_drupal_entity = reset($client_drupal_entities);
}
// Get the auth server object from that uses the League library.
try {
// Respond to the incoming request and fill in the response.
$auth_server = $this->grantManager->getAuthorizationServer($grant_type_id, $client_drupal_entity);
$response = $this->handleToken($request, $auth_server);
}
catch (OAuthServerException $exception) {
watchdog_exception('simple_oauth', $exception);
$response = $exception->generateHttpResponse(new Response());
}
return $response;
}
The request is send as form data:
See example js code below:
(username is accepted, email param is added to demonstrate whats needed)
var formdata = new FormData();
formdata.append("grant_type", "password");
formdata.append("client_id", "828472a8-xxxx-xxxx-xxx-ab041d3b313a");
formdata.append("client_secret", "secret-xxx-xxx-xxx");
//formdata.append("username", "username");
formdata.append("email", "email#email.com");
formdata.append("password", "password");
var requestOptions = {
method: 'POST',
body: formdata,
redirect: 'follow'
};
fetch("{{base_url}}oauth/token", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));

405 error with Ajax POST / Nginx configuration

I'm trying to send email with an Ajax form and swiftmailer. It works in local but not in production.
When contact_me.php takes parameters not from form but written explicitly the email is sent even from the server so I think Swiftmailer is working.
contact_me.js
// Contact Form Scripts
$(function() {
$("#contactForm input,#contactForm textarea").jqBootstrapValidation({
preventSubmit: true,
submitError: function($form, event, errors) {
// additional error messages or events
},
submitSuccess: function($form, event) {
event.preventDefault(); // prevent default submit behaviour
// get values from FORM
var name = $("input#name").val();
var email = $("input#email").val();
var phone = $("input#phone").val();
var message = $("textarea#message").val();
var firstName = name; // For Success/Failure Message
// Check for white space in name for Success/Fail message
if (firstName.indexOf(' ') >= 0) {
firstName = name.split(' ').slice(0, -1).join(' ');
}
$.ajax({
url: "././mail/contact_me.php",
type: "POST",
data: {
name: name,
phone: phone,
email: email,
message: message
},
dataType: "text",
cache: false,
success: function() {
// Success message
},
error: function() {
// Fail message
},
});
},
filter: function() {
return $(this).is(":visible");
},
});
$("a[data-toggle=\"tab\"]").click(function(e) {
e.preventDefault();
$(this).tab("show");
});
});
/*When clicking on Full hide fail/success boxes */
$('#name').focus(function() {
$('#success').html('');
});
contact_me.php
<?php
// Autoload for swiftmailer
require_once '../vendor/autoload.php';
// Check for empty fields
if(empty($_POST['name']) ||
empty($_POST['email']) ||
empty($_POST['phone']) ||
empty($_POST['message']) ||
!filter_var($_POST['email'],FILTER_VALIDATE_EMAIL))
{
echo "No arguments Provided!";
return false;
}
$name = strip_tags(htmlspecialchars($_POST['name']));
$email_address = strip_tags(htmlspecialchars($_POST['email']));
$phone = strip_tags(htmlspecialchars($_POST['phone']));
$message = strip_tags(htmlspecialchars($_POST['message']));
// Create the email and send the message
$email_subject = "TrustPair nouveau contact : $name";
$email_body = "New form.\n\n"."Here are the details:\n\nName: $name\n\nEmail: $email_address\n\nPhone: $phone\n\nMessage:\n$message";
// Add here swiftmailer code, need to return true
// Create the Transport
$transport = (new Swift_SmtpTransport('mail.gandi.net', 465, "ssl"))
->setUsername('name#domain.com')
->setPassword('password')
;
// Create the Mailer using your created Transport
$mailer = new Swift_Mailer($transport);
// Create the message
$message = (new Swift_Message())
// Give the message a subject
->setSubject($email_subject)
// Set the From address with an associative array
->setFrom(['noreply#domain.com' => 'Domain no reply'])
// Set the To addresses
->setTo(['firstmailto#gmail.com', 'secondmailto#gmail.com'])
// Give it a body
->setBody($email_body)
;
// Send the message
$result = $mailer->send($message);
echo $result;
// result is equal to the nbr of message recipients
if ($result == 0) {
return false;
} else {
return true;
}
?>
Nginx server doesn't allow POST request with static page (ie. *.html).
There are hacks to handle the problem. In my case, it fix the 405 error but the emails weren't send.
The solution was to change the index.html to index.php, be sure to adapt your Nginx configuration to reflect this changes.

Ajax call using angular js

I am a new Angularjs user.I am facing a problem,when i submit a signup form,I have applied validation using AngularJs. At the same time if all the input fields are valid then i have send an $http Ajax call to check the email address,already exist or not.The issue is my php file did not receive email data.
$http({
method : 'POST',
async: false,
url: 'http://localhost/angular/signup/emailcheck.php',
data: { email: $scope.user.email }, // pass in data as strings
headers : { 'Content-Type': 'application/x-www-form-urlencoded' } // set the headers so angular passing info as form data (not request payload)
})
.success(function(data)
{
$scope.info = data;
if($scope.userForm.$valid && $scope.info === '0') {
alert('our form is amazing' + $scope.info);
}
else{
alert('Already exist');
}
}).error(function(response,status)
{
console.log('ERROR HERE'+ status);
});
My Php file code:
$email = $_POST['email'];
$sql = "SELECT * FROM user where username = '".$email."'";
$result = mysql_query($sql);
//fetch tha data from the database
while ($row = mysql_fetch_array($result)) {
....
....
....
....
....
}
I have checked and found that php file did not receive email value at all.
$http({
method : 'POST',
async: false,
url: 'http://localhost/angular/signup/emailcheck.php',
data : $.param($scope.user), // this will definitely wor
headers : { 'Content-Type': 'application/x-www-form-urlencoded' } // set the headers so angular passing info as form data (not request payload)
})
.success(function(data)
{
$scope.info = data;
if($scope.userForm.$valid && $scope.info === '0') {
alert('our form is amazing' + $scope.info);
}
else{
alert('Already exist');
}
}).error(function(response,status)
{
console.log('ERROR HERE'+ status);
});
Try removing http://localhost from url and then see it may be CORS.
Just a guess: your url is pointing to localhost but has no port number, this is unusual, maybe you forgot it?
data: $.param({
email:$scope.user.email
})
Or this way: (modify the php)
Angular HTTP post to PHP and undefined
I have just found that in php file,
$_POST or $_GET will not work, to receive data.
Use the following:
$data = file_get_contents("php://input");
$objData = json_decode($data);
$email = $objData->email;
In my case it works.

PHP file not detected in my AngularJS project

I have an AngularJS app which has a mailer script written in PHP. I'm trying to refer to the PHP file via the angular $http service but I keep getting a 404 error when I try to use it via my contact form, in the corresponding controller, like so:
angular.module('myModule')
.controller('contactUsController', ['$scope', '$http', function ($scope, $http) {
$scope.formData = {};
$scope.submitted = false;
$scope.submit = function(contactform) {
console.log('Form data', $scope.formData);
$scope.submitted = false;
$scope.submitButtonDisabled = true;
if (contactform.$valid) {
$http({
method : 'POST',
url : "app/process.php",
data : $.param($scope.formData),
headers : { 'Content-Type': 'application/x-www-form-urlencoded' }
}).success(function(data){
console.log(data);
if (!data.success) {
// if not successful, bind errors to error variables
$scope.errorName = data.errors.name;
$scope.errorEmail = data.errors.email;
$scope.errorTextarea = data.errors.message;
$scope.submissionMessage = "Sorry. Error sending message. Please try again.";
$scope.submission = true; //shows the error message
} else {
// if successful, bind success message to message
$scope.formData = {}; // form fields are emptied with this line
$scope.submissionMessage = "Thank you! Your message has been sent successfully.";
$scope.submitted = true; //shows the success message
}
});
} else {
}
}
}]);
So each time I invoke the submit() function by pressing the send button, the browser complains like so:
I've been searching around for an answer, but I haven't found one that could help me out.
I am using npm start to run my app. My project structure is as shown in the image below:
Any idea what could be going wrong? Any help is appreciated.

How to response to all clients with websocket?

I'm working on a small project with PHP-Websocket.
The Server side is running with this https://github.com/ghedipunk/PHP-Websockets
Server side:
require "PHP-Websockets/websockets.php";
class Server extends WebSocketServer
{
private $_connecting = 'Connecting..';
private $_welcome = 'SOCKET SERVER!';
protected function connected($user)
{
// Send welcome message to user when connected
}
protected function process($user, $message)
{
// data sent from client
$json = json_decode($message);
//prepare data response to client
$response = json_encode(array('type'=>'notify', 'message'=>'Client'.$user->id.' has sent a request.'));
$this->send($user, $response);
}
protected function closed($user)
{
// Alert on server
echo "User $user->id has closed the connection".PHP_EOL;
}
public function __destruct()
{
echo "Server Closed!".PHP_EOL;
}
}
$addr = 'localhost';
$port = '2207';
$server = new Server($addr, $port);
$server->run();
Client Side:
<script>
var uri = "ws://localhost:2207";
function socket_connect(){
socket = new WebSocket(uri);
if(!socket || socket == undefined) return false;
socket.onopen = function(){
console.log('Connected to Server!');
}
socket.onerror = function(){
console.log('Connection Failed!');
}
socket.onclose = function(){
socket_log('Connection Closed! ')
}
socket.onmessage = function(e){
//var response_data = e.data;
var msg = JSON.parse(e.data); //PHP sends Json data to client
console.log(msg.message);
var new_response = '<li>'+msg.message+'</li>;
$('#response').append(new_response);
}
}
function send_data_to_server(data){
if(!socket || socket == undefined) return false;
socket.send(JSON.stringify(data));
}
$(document).ready(function(){
socket_connect();
$('#send_request').click(function(){
send_data_to_server({message: 'Message sent from Client'});
});
});
</script>
<input type="button" id="send_request" value="Send Request to Server" />
<ul id="responses"></ul>
Everything works fine with those code above.
When Client1 sends a request to Server, the Server responses to him instantly. BUT the other clients can not see the response message.
So I want to make it go further : When a client sends a request to the server, the server will response to ALL clients so that all client can see the message.
How can I do that?
Thanks in advance && sorry for my bad English!
When a user connect, you need to add him to an array with every other users.
When one disconnect, remove him from this array.
Then when you want to send a message to every user, iterate on the array and send the message to each connected user.
WebSocketServer class has WebSocketServer::$users variable.
If you iterate over WebSocketServer::$users in split_packet function and then call main process it will work. In latest source code please iterate in line no-405.
//original
if ((preg_match('//u', $message)) || ($headers['opcode']==2)) {
//$this->stdout("Text msg encoded UTF-8 or Binary msg\n".$message);
$this->process($user, $message);
} else {
$this->stderr("not UTF-8\n");
}
//have to change
if ((preg_match('//u', $message)) || ($headers['opcode']==2)) {
//$this->stdout("Text msg encoded UTF-8 or Binary msg\n".$message);
foreach($this->users as $usr){
$this->process($usr, $message);
}
} else {
$this->stderr("not UTF-8\n");
}

Categories