I have a registration form,i want to redirect the user after register success (200) response to "location" => "home.php" or display errors on 400 (bad request) via json
I only know few basics of php so how should this look like
--> register.php ?
Combined with the examples below?
// make sure nothing is echo'd or otherwise sent to the
// output buffer at this stage
$errors = []; // collect errors in here
// do whatever you need to do with the $_POST / $_FILES data...
// capturing errors example...
if ($_POST['cpassword'] != $_POST['password']) {
$errors[] = "Passwords do not match!";
}
// use content negotiation to determine response type
if ($_SERVER['HTTP_ACCEPT'] === "application/json") {
if (count($errors)) {
header("Content-type: application/problem+json");
http_response_code(400);
exit(json_encode([
"message" => "Invalid form data or something",
"errors" => $errors
]));
}
header("Content-type: application/json");
exit(json_encode(["location" => "home.php"]));
}
// just a normal request, respond with redirects or HTML
// ...
foreach ($errors as $error) : ?>
<div class="error"><?= $error ?></div>
<?php endforeach;
The client can navigate to home on success or display error information otherwise
document.querySelector(".register form").addEventListener("submit", async (e) => {
e.preventDefault()
const form = e.target
const body = new FormData(form)
// fetch is much easier to use than XHR
const res = await fetch(form.action, {
method: "POST",
headers: {
accept: "application/json", // let PHP know what type of response we want
},
body
})
const data = await res.json()
if (res.ok) {
location.href = data.location
} else if (res.status === 400) {
document.querySelector('.msg').textContent = data.message
// also do something with data.errors maybe
}
})
Please understand that im new and i have trouble resolving this,
a complete php answer would help & mark as resolved
You have no ok element in the JSON when it contains the redirect location. So change
exit(json_encode(["location" => "home.php"]));
to
exit(json_encode(["ok" => true, "location" => "home.php"]));
Related
EDIT : I resolved my issue as I had a forgotten "require" operator messing up in the code. Sorry for not being aware of this earlier and thanks for your time.
I'm kinda new to web developpement and it's the second time only I use AJAX on a website.
It's just about a contact form validation using ajax and php client side validation.
Here is the problem : my code is actually working as expected for the validation part as everything works fine but I don't understand what I'm missing or doing wrong cause I get a line on top of my website (on each page, not only the contact page btw ) that I don't want obviously
I understand that it comes from my php code actually echoing my json_encode($data) but i don't get why and how to do to avoid this
Here is my code :
JS :
let resultMessage = $('#resultMessage')
let form = $('#contact_form')
form.submit(function(e){
$('span.error').empty()
e.preventDefault()
$.ajax({
type: "POST",
url: form.attr("action"),
data: form.serialize(),
dataType: 'json',
success: function(response) {
if(response.success == true){
resultMessage.html('Message sent succesfully')
} else {
resultMessage.html('Fail')
if (response.errors.nom != null) {
$('#name_error').html(response.errors.nom);
}
if (response.errors.email != null) {
$('#email_error').html(response.errors.email);
}
if (response.errors.message != null) {
$('#message_error').html(response.errors.message);
}
}
},
error: function(){
console.log('error')
}
})
})
PHP
$success = false;
$errors = [];
// inputs validation
$errors = textInputValidation($errors, $name, 'name', 2, 50);
$errors = emailValidation($errors, $email, 'email');
$errors = textInputValidation($errors, $message, 'message', 10, 5000);
// if there is no error =>
if (count($errors) == 0) {
// code actualy sending the message
$success = true;
}
$data = array(
'errors' => $errors,
'success' => $success
);
header('Content-type:application/json');
echo json_encode($data);
So this code is working but the problem is that I get this line on top of my website
{"errors":{"name":"please fill this field","email":"please fill this field","message":"please fill this field"},"success":false}
It's on each page, not only the contact page, and it's not even changing when the validation is okay and there is no errors in the form or anywhere.
I'm probably missing something very basic, sorry for that.
Thanks for your help
Okey so I've got a little problem with MailChimp response. So here is the thing.
I want to check the status of the subscribed user. I have the PHP code which is works fine and i have the code which is also works fine so I get the response BUT I can't use the response after it. So here is the codes:
I have a MailService provider which contain this function:
postCheck(post: {email: string}): Observable<any>{
const email = JSON.stringify(post);
let headers = new Headers();
headers.append('Content-Type', 'application/x-www-urlencoded');
return this.http.post('http://localhost:8100/getapi', email, {
headers: headers
}).map(res => {
console.log(res.json())
return res.json(); //add this line
});
}
In the main page I have this function:
sendCheck(email: string){
this.mailservice.postCheck({email: email})
.subscribe(
response => this.response = response.status,
error => console.log(error)
);
}
In the main page html when i call <p>{{ response }}</p> it write out 'pending' or 'subscribed'. But after it when I try console.log(this.response); it write out nothing so in the code I can't really do the checking.
From what I can gather, you want to do something with your response after the data has arrived. This you need to do inside the subscription, to ensure that the data is available. So something like this:
sendCheck(email: string){
this.mailservice.postCheck({email: email})
.subscribe(response => {
this.response = response.status;
// here the value has been set to response, so do what you want
this.doSomethingWithResponse();
)};
}
doSomethingWithResponse() {
if(this.response == 'subscribed') {
// do stuff
}
}
I have a file ajax.php which I am using to process data passed through jquery. I have this particular line of code called on successful form verification:
$.post("/ajax.php",{'request': 'emailLogin', 'loginmail': mail, 'loginpass': pass}, function(data) {} );
data in my case is: {"valid":true}{"auth":false}which is returned as a response from ajax.php, but I can't seem to file the correct way of defining "auth" and a variable with value "false".
My ajax.php is just checking if login and password are in the database and than echo json_encode(array('auth' => false)); or echo json_encode(array('auth' => true)); depending on the result. But it has also contain these lines:
if( isset($_POST['loginmail'])) {
$usermail = htmlspecialchars($_POST['loginmail']);
if (!filter_var($usermail, FILTER_VALIDATE_EMAIL)) {
$response = array('valid' => false, 'message' => 'You did not enter a correct email address.');
} else {
// All good
$response = array('valid' => true);
}
}
echo json_encode($response);
Don't echo json_encode($response) separately from the authentication result, you need to combine them. After you do the authentication, do:
$response['auth'] = $result_of_authentication;
then do
echo json_encode($response);
Once you do this, you should be able to access data.auth in Javascript. You should tell $.post that it's returning JSON:
$.post("/ajax.php",{
'request': 'emailLogin',
'loginmail': mail,
'loginpass': pass},
function(data) {
alert(data.auth);
},
"json");
Based on your PHP code you should be able to access the valid attribute like so:
$.post("/ajax.php",{'request': 'emailLogin', 'loginmail': mail, 'loginpass': pass}, function(data) {
var auth = data.valid;
if (auth) {
// do something!
} else {
// do something else!
}
});
Also there is a bug in your PHP code, you need to set up a default value for $response like so:
$response = array('valid' => false, 'message' => 'Email address is required');
if( isset($_POST['loginmail'])) {
$usermail = htmlspecialchars($_POST['loginmail']);
if (!filter_var($usermail, FILTER_VALIDATE_EMAIL)) {
$response = array('valid' => false, 'message' => 'You did not enter a correct email address.');
} else {
// All good
$response = array('valid' => true);
}
}
echo json_encode($response);
Otherwise if $_POST['loginmail'] is not set your app with throw an undefined variable exception
EDIT:
As Barmar pointed out in his answer, you should only echo a response back once time to avoid creating an invalid response. Any data you need should be sent back in a single array. I don't see you doing that in your PHP code but you do make mention of echoing another array ['auth' => false] which will not work the way you want it to
I keep getting the error alert. There is nothing wrong with the MYSQL part, the query gets executed and I can see the email addresses in the db.
The client side:
<script type="text/javascript">
$(function() {
$("form#subsribe_form").submit(function() {
var email = $("#email").val();
$.ajax({
url: "subscribe.php",
type: "POST",
data: {email: email},
dataType: "json",
success: function() {
alert("Thank you for subscribing!");
},
error: function() {
alert("There was an error. Try again please!");
}
});
return false;
});
});
</script>
The server side:
<?php
$user="username";
$password="password";
$database="database";
mysql_connect(localhost,$user,$password);
mysql_select_db($database) or die( "Unable to select database");
$senderEmail = isset( $_POST['email'] ) ? preg_replace( "/[^\.\-\_\#a-zA-Z0-9]/", "", $_POST['email'] ) : "";
if($senderEmail != "")
$query = "INSERT INTO participants(col1 , col2) VALUES (CURDATE(),'".$senderEmail."')";
mysql_query($query);
mysql_close();
$response_array['status'] = 'success';
echo json_encode($response_array);
?>
You need to provide the right content type if you're using JSON dataType. Before echo-ing the json, put the correct header.
<?php
header('Content-type: application/json');
echo json_encode($response_array);
?>
Additional fix, you should check whether the query succeed or not.
if(mysql_query($query)){
$response_array['status'] = 'success';
}else {
$response_array['status'] = 'error';
}
On the client side:
success: function(data) {
if(data.status == 'success'){
alert("Thank you for subscribing!");
}else if(data.status == 'error'){
alert("Error on query!");
}
},
Hope it helps.
Just so you know, you can use this for debugging. It helped me a lot, and still does
error:function(x,e) {
if (x.status==0) {
alert('You are offline!!\n Please Check Your Network.');
} else if(x.status==404) {
alert('Requested URL not found.');
} else if(x.status==500) {
alert('Internel Server Error.');
} else if(e=='parsererror') {
alert('Error.\nParsing JSON Request failed.');
} else if(e=='timeout'){
alert('Request Time out.');
} else {
alert('Unknow Error.\n'+x.responseText);
}
}
Some people recommend using HTTP status codes, but I rather despise that practice. e.g. If you're doing a search engine and the provided keywords have no results, the suggestion would be to return a 404 error.
However, I consider that wrong. HTTP status codes apply to the actual browser<->server connection. Everything about the connect went perfectly. The browser made a request, the server invoked your handler script. The script returned 'no rows'. Nothing in that signifies "404 page not found" - the page WAS found.
Instead, I favor divorcing the HTTP layer from the status of your server-side operations. Instead of simply returning some text in a json string, I always return a JSON data structure which encapsulates request status and request results.
e.g. in PHP you'd have
$results = array(
'error' => false,
'error_msg' => 'Everything A-OK',
'data' => array(....results of request here ...)
);
echo json_encode($results);
Then in your client-side code you'd have
if (!data.error) {
... got data, do something with it ...
} else {
... invoke error handler ...
}
In order to build an AJAX webservice, you need TWO files :
A calling Javascript that sends data as POST (could be as GET) using JQuery AJAX
A PHP webservice that returns a JSON object (this is convenient to return arrays or large amount of data)
So, first you call your webservice using this JQuery syntax, in the JavaScript file :
$.ajax({
url : 'mywebservice.php',
type : 'POST',
data : 'records_to_export=' + selected_ids, // On fait passer nos variables, exactement comme en GET, au script more_com.php
dataType : 'json',
success: function (data) {
alert("The file is "+data.fichierZIP);
},
error: function(data) {
//console.log(data);
var responseText=JSON.parse(data.responseText);
alert("Error(s) while building the ZIP file:\n"+responseText.messages);
}
});
Your PHP file (mywebservice.php, as written in the AJAX call) should include something like this in its end, to return a correct Success or Error status:
<?php
//...
//I am processing the data that the calling Javascript just ordered (it is in the $_POST). In this example (details not shown), I built a ZIP file and have its filename in variable "$filename"
//$errors is a string that may contain an error message while preparing the ZIP file
//In the end, I check if there has been an error, and if so, I return an error object
//...
if ($errors==''){
//if there is no error, the header is normal, and you return your JSON object to the calling JavaScript
header('Content-Type: application/json; charset=UTF-8');
$result=array();
$result['ZIPFILENAME'] = basename($filename);
print json_encode($result);
} else {
//if there is an error, you should return a special header, followed by another JSON object
header('HTTP/1.1 500 Internal Server Booboo');
header('Content-Type: application/json; charset=UTF-8');
$result=array();
$result['messages'] = $errors;
//feel free to add other information like $result['errorcode']
die(json_encode($result));
}
?>
Server side:
if (mysql_query($query)) {
// ...
}
else {
ajaxError();
}
Client side:
error: function() {
alert("There was an error. Try again please!");
},
success: function(){
alert("Thank you for subscribing!");
}
adding to the top answer: here is some sample code from PHP and Jquery:
$("#button").click(function () {
$.ajax({
type: "POST",
url: "handler.php",
data: dataString,
success: function(data) {
if(data.status == "success"){
/* alert("Thank you for subscribing!");*/
$(".title").html("");
$(".message").html(data.message)
.hide().fadeIn(1000, function() {
$(".message").append("");
}).delay(1000).fadeOut("fast");
/* setTimeout(function() {
window.location.href = "myhome.php";
}, 2500);*/
}
else if(data.status == "error"){
alert("Error on query!");
}
}
});
return false;
}
});
PHP - send custom message / status:
$response_array['status'] = 'success'; /* match error string in jquery if/else */
$response_array['message'] = 'RFQ Sent!'; /* add custom message */
header('Content-type: application/json');
echo json_encode($response_array);
I had the same issue. My problem was that my header type wasn't set properly.
I just added this before my json echo
header('Content-type: application/json');
...you may also want to check for cross site scripting issues...if your html pages comes from a different domain/port combi then your rest service, your browser may block the call.
Typically, right mouse->inspect on your html page.
Then look in the error console for errors like
Access to XMLHttpRequest at '...:8080' from origin '...:8383' has been blocked by
CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested
resource.
I have the following:
YUI().use("io-form",
function(Y) {
var cfg = {
method: 'POST',
form: {
id: 'subscribe-form',
useDisabled: false
}
};
function login() {
Y.io('process.php', cfg);
Y.on('io:success', onSuccess, this);
Y.on('io:failure', onFailure, this);
};
function onSuccess(id,response,args) {
document.getElementById('myformmsg').innerHTML = response.responseText;
document.forms['myform'].reset();
};
function onFailure(id,response,args) {
document.getElementById('myformmsg').innerHTML = "Error, retry...";
document.forms['myform'].reset();
};
Y.on('click', login, '#myformbutton', this, true);
});
How does yui know whether to go into onSucces of onFailure. What do I have to return from PHP?
It depends on the header returned http status code.
let say status code 200, it will goes to onSuccess.
let say status code 500 (internal server error), it will goes to onFailure.
List of HTTP status code here: http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
If you have some fatal error in php, it will still returns status 200 because the request is successful.
If you would like to handle php errors, I would suggest you to have an json return like everytime on success:
{
status: 0, // Let say 0 for OK, -1 for Error, you can define more by yourself
results: <anything you want here>,
errors: <errors message/errors code for your ajax handler to handle>
}
it can be done in php like this:
$response = array(
'status' => 0,
'results' => 'something good ...',
'errors' => 'error message if status is -1'
);
echo json_encode($response);
In your javascript, you will be handling like this:
function onSuccess(id,response,args) {
var responseObj = Y.JSON.parse(response);
if (responseObj.status === 0) {
// Request and process by php successful
}
else {
// Error handling
alert(responseObj.errors);
}
};
Remember, if you wanted to use Y.JSON, you need to include 'json-parse', example:
YUI().use('json-parse', , function (Y) {
// JSON is available and ready for use. Add implementation
// code here.
});