When ever I am doing an ajax request with jquery I always get an error 500 return,
I am posting to the following URL
http://localhost/domain/index.php/my_profile/interests_music
using this javascript,
$("#add").click(function(e){
//set some process variables, we need to get the forms action,
//and any post data it is sending appending isAjax into the params
//gives us a point in the controller to gracefully check for ajax.
var action = $(this).parent('form').attr('action');
var formData = $(this).parent('form').serialize()+"&isAjax=1";
$.ajax({
type: "POST",
url: action,
data: formData
}).done(function( msg ) {
alert( "Data Saved: " + msg );
});
e.preventDefault();
});
The params that are being sent are,
music=Savage Garden&isAjax=1
And the PHP method the ajax is requesting looks like this,
public function interests_music()
{
if($this->input->post('music'))
{
$this->rest->initialize(array('server' => 'https://www.googleapis.com/freebase/v1'));
$response = $this->rest->get('mqlread?query={"type":"/music/artist","name":"' . urlencode($this->input->post('music')) . '","id":[]}');
$data['image'] = 'https://usercontent.googleapis.com/freebase/v1/image'.$response->result->id[0].'?mode=fillcrop&maxwidth=80&maxheight=80';
$data['category'] = 'music';
$data['user_id'] = $this->session->userdata('id');
$data['name'] = $this->input->post('music', TRUE);
$this->profile_model->add_interest($data);
Events::trigger('interests_music');
Events::trigger('badge_stagediver');
if($this->input->post('isAjax') == 1)
{
echo json_endcode($data);
$this->_buttons();
}
redirect('my_profile/interests');
}
else
{
show_404();
}
}
Am I missing something, is this a common problem?
Well for one there's a typo in your PHP which could be what your server is choking on: echo json_endcode($data); should be echo json_encode($data);. Aside from that there could be other issues with your HTTP server. What server are you using? A good practice is to find the server error log and PHP error log and use tail -f or some other method of monitoring the logs which should give you more information when you have 505s.
Related
I'm trying to send form data to a table called attendants. I have the form, the AJAX and query created, but when trying to test (when submitting the form), I see a POST http://localhost/rsvp/wp-admin/admin-ajax.php 400 (Bad Request) error on console.
Unsure what's causing this as when I run a console.log(ajaxurl); the URL it returns is http://localhost/rsvp/wp-admin/admin-ajax.php which is correct.
Unsure what's happening here?
EDIT: I've recently discovered that http://localhost/rsvp/wp-admin/admin-ajax.php returns 0.
form.php (Folder Path: rsvp > template-parts > parts > form.php) :
<div class="form sectionPadding" id="rsvp-form">
<form id="rsvpForm" method="post">
<?php get_template_part('template-parts/snippets/form-step-1'); ?>
<?php get_template_part('template-parts/snippets/form-step-2'); ?>
</form>
</div>
<script type="text/javascript">
var ajaxurl = '<?php echo admin_url('admin-ajax.php'); ?>';
</script>
form.js (form.js compiles into theme.min.js. The path to theme.min.js is rsvp > assets > build > js > theme.min.js) :
jQuery('#rsvpForm').on('submit', function(e) {
e.preventDefault();
jQuery.ajax({
action: 'send_to_db',
dataType: "text",
type: "post",
data: $('form').serialize(),
url: ajaxurl,
success: function(data) {
console.log(data);
},
error: function() {
console.log("Error");
}
});
});
functions.php
add_action("wp_ajax_send_to_db", "send_to_db");
add_action("wp_ajax_nopriv_send_to_db", "send_to_db");
function send_to_db(){
if (isset($_POST['submit'])) {
global $wpdb;
$first_name = $_POST['fname'];
$table_name = $wpdb->prefix . "attendants";
$row_result = $wpdb->query("INSERT INTO $table_name (first_name) VALUES ('$first_name')" );
if ($row_result == 1){
echo "submitted";
} else{
echo "error";
}
die();
}
}
To summarize, my folder structure is:
rsvp
assets
build
js
theme.min.js
template-parts
parts
form
form.php
form.js
functions.php
EDIT: I've recently discovered that
http://localhost/rsvp/wp-admin/admin-ajax.php returns 0.
That's indeed the expected return value when the request (URL) doesn't contain the AJAX action name. Additionally, the HTTP response status would also be a 400 Bad Request which basically means "missing action name" or "there's no callback registered for that action".
And in your case, it seems that your AJAX script is not sending the AJAX action.
Because in your form.js script, the action parameter should be in the data — and as far as I know, jQuery.ajax() doesn't have a action property:
jQuery.ajax({
action: 'send_to_db', // this should be in 'data'
...
data: $('form').serialize(),
...
});
So you can do data: $('form').serialize() + '&action=send_to_db' like so:
jQuery.ajax({
...
data: $('form').serialize() + '&action=send_to_db',
...
});
That way, WordPress would recognize the AJAX action (via $_REQUEST['action']) and then run the proper AJAX handler / PHP callback, which is send_to_db() in your case.
And you can confirm if your AJAX callback is registered properly by visiting /wp-admin/admin-ajax.php?action=send_to_db — are you still seeing a 0?
Update
If the HTTP response status is no longer 400 (where it should now be 200), then it means your AJAX request is sending an action (send_to_db in your case) and that there's a PHP callback registered for that AJAX action (wp_ajax_send_to_db / wp_ajax_nopriv_send_to_db).
But because your callback is only doing something when the POST variable submit is set, then if your AJAX request data doesn't include that, the response would still be a 0.
If you want to avoid that, then you can do something like so:
function send_to_db() {
if ( isset( $_POST['submit'] ) ) {
// ... your code here.
//die();
} else {
echo 'Invalid request!';
}
wp_die(); // It's recommended to always call this to end an AJAX request,
// but die() is OK, too.
}
And with that, when you manually go to /wp-admin/admin-ajax.php?action=send_to_db (i.e. without sending any POST data), you'd see Invalid request! on the page. window.fetch( '/wp-admin/admin-ajax.php?action=send_to_db' ) would even receive that same response.
So now that the error 400 is gone, you just need to make sure your AJAX request is sending the proper data and that your PHP callback is working (or doing what it needs to do). And on Chrome, you can easily inspect the request and response data, headers, etc. by opening the developer tools and go to the Network → XHR tab and simply click on the relevant request.
Your SQL query is highly insecure and I strongly suggest you to use wpdb::prepare() to prepare the query for safe execution:
//$row_result = $wpdb->query("INSERT INTO $table_name (first_name) VALUES ('$first_name')" );
$query = $wpdb->prepare(
"INSERT INTO $table_name (first_name) VALUES (%s)",
sanitize_text_field( $first_name )
);
$row_result = $wpdb->query( $query );
Alternatively, for inserting a single database row/entry, you can just use wpdb::insert():
$row_result = $wpdb->insert( $table_name, array(
'first_name' => sanitize_text_field( $first_name ),
) );
And I have actually tested your original PHP callback, and it worked, so long as the request data are good. :)
I'm having some HTML text in my response from an API.
Response I got
Preview's response
Here is my code (PHP):
public function getBeatmapInformations() {
$this->render(false);
if($this->request->is('get')){
$url = $_GET['beatmapUrl'];
$isOsuUrlBeatmap = "#^(?:https://)?osu\.ppy\.sh/(?:b|beatmapsets)/(\d*)#";
if(preg_match($isOsuUrlBeatmap, $url, $matches)){
$OSU_API_KEY = "MY_API_KEY";
$httpClient = new Client();
$response = $httpClient->get('https://osu.ppy.sh/api/get_beatmaps', [
's' => intval($matches[1]),
'k' => $OSU_API_KEY
]
);
$result = $response->body();
if(!empty($result)){
echo $result;
}
}
}
}
Javascript side (AJAX request):
function launchAjaxRequest(beatMapUrl) {
let url = beatMapUrl.replace(/['"]+/g, '');
$.get({
type : "GET",
url: '/ofv/getBeatmapInformations',
data: {
beatmapUrl : url,
},
success: function(data){
fillModesAvailablesForBeatmap(data);
}
});}
You should not manually echo anything in your controllers actions in CakePHP. The way to achieve json output in CakePHP is to use Data Views with Request Handler:
1.Enable Request Handler in your controller's initialize() method:
public function initialize(){
$this->loadComponent("RequestHandler");
}
2.In your action, set your data to be serialized:
$result = $response->body();
$this->set(compact("result"));
$this->set("_serialize", "result");
More about Request Handler and Data Views can be found in docs: JSON and XML views
As probably someone will point it out, you have also an alternative here: you can simply stop execution of script right after echoing data with die(). But it is not the Cake way of handling this.
Trying to do a simple ajax post, for some reason, it is not posting my data! It successfully posts to the file (ajaxpost.php) but no POST data is passed..
var myKeyVals = {caption: "test"};
$.ajax({ //Process the form using $.ajax()
type : 'POST', //Method type
url : 'ajaxpost.php', //Your form processing file url
data : myKeyVals, //Forms name
dataType : 'json',
success : function(data) {
if (!data.success) { //If fails
if (data.errors.name) { //Returned if any error from process.php
$('.throw_error').fadeIn(1000).html(data.errors.name); //Throw relevant error
}
} else {
$('#success').fadeIn(1000).append('<p>' + data.posted + '</p>'); //If successful, than throw a success message
}
}
});
Here is my AjaxPost.php..
<?php
$text = $_GET['caption'];
$file = 'people.txt';
// Open the file to get existing content
$current = file_get_contents($file);
// Append a new person to the file
$current = "LOG: " . $text . "\n";
// Write the contents back to the file
file_put_contents($file, $current, FILE_APPEND);
?>
In your php file you're using $_GET['caption'] but you should be using $_POST['caption'] as this is a post request.
POST data is accessed in PHP using $_POST, not $_GET !
Alternatively, if you wish to support both HTTP methods you can use $_REQUEST.
Hello fellow programmers!
I'm fairly new to PHP/JavaScript and have to admit it is quite the learning experience, but I am enjoying it quite a bit. I have a bit of a problem when I'm saving to a Database using Ajax however. The save works perfectly fine, but instead of falling into my "success" code it falls into the "error" section and gives me a Status of 200. I'm not sure what the status 200 means and am confused because it does actually save to the Database correctly. Eventually what I want to do is use a JavaScript function to updated fields (when successfully saving to the DB), but right now I'm just trying to display a message to the user. Also, in the JavaScript code I have to have the single quotes (') around the ajax variables (i.e. url, type, dataType, etc.) for it to work. I've tried adding the single quotes around success and error and their associated functions to no avail. Thanks!
Javascript:
function SaveUserBlankAnswer(form) {
if (form.Answer.value != "") {
var answer = form.Answer.value;
var contentID = form.ContentID.value;
var userID = form.UserID.value;
$.ajax({
'url': 'Database/SaveUserBlankAnswer_db.php',
'type': 'POST',
'dataType': 'json',
'data': { ContentID: contentID, UserID: userID, Answer: answer },
success: function(){
alert('BOOSH!');
},
error: function(data){
alert(data.status);
}
});
}
}
PHP:
<?php
session_start();
include("DBConnection.php");
$duplicateCheck = "SELECT UserID FROM BlankAnswer WHERE ContentID = " . $_POST[ContentID] . " AND UserID = " . $_POST[UserID];
if ($duplicateResult = $mysqli->query($duplicateCheck)) {
$rowCount = $duplicateResult->num_rows;
if ($rowCount == 0) {
$SQL = "INSERT INTO BlankAnswer (UserID, ContentID, Answer)
VALUES('$_POST[UserID]', '$_POST[ContentID]', '$_POST[Answer]');";
} else {
$SQL = "UPDATE BlankAnswer SET Answer = '" . $_POST[Answer] . "' WHERE ContentID = '" . $_POST[ContentID] . "' AND UserID = '" . $_POST[UserID] . "'";
}
$mysqli->query($SQL);
}
$mysqli->close();
?>
Use Jquery serialize method to create the form data for submission as you are not escaping the data on directly passing it.
Return 1 on success and 0 in failure from PHP script. No data is bad. Your POST request has no response, so maybe it thinks as an error. and the error in callback is for AJAX error. You can pass 0 or any message on DB level error.
function SaveUserBlankAnswer(form) {
//do validations here
var formData = $('#formId').serialize();
$.ajax({
type: "post",
url: "Database/SaveUserBlankAnswer_db.php",
dataType:"json",
data: formData,
success: function (data) {
if(data.status === "1") {
//Show success
} else if(data.status === "0") {
// alert for error on saving to DB
}
},
error: function(error){
alert('AJAX ERROR');
}
});
}
Hope it helps
Happy Coding !!!
I've made a simple autoload function that loads content when you scroll down on a website. However, there seems to be a few problems when i enable CSRF protection in Codeigniter.
I'm not using a form, so i don't know how i can send the token from A to B when i'm doing my post request as you scroll.
My JavaScript
if (location.href == baseurl) {
$(window).scroll(function(){
if ($(window).scrollTop() > $('body').height() / 2) {
if(doScroll == 1) {
$.post(baseurl + 'ajax/images',{'id' : ID}, function(data) {
$("#wrapper_content").append(data);
if(data == 'Det finnes ikke flere bilder i databasen, WTF!? Send inn forslag ASAP!') {
doScroll = 0;
}
ID++;
});
}
}
});
}
Since Codeigniter expects a TOKEN on all POST request i can't get this to work when CSRF i enabled. Any suggestions?
Error when CSRF is Enabled
Failed to load resource: the server responded with a status of 500 (Internal Server Error)
If i turn CSRF off, everything works great...
You might like to try this code I've used. It works great:
<script type="text/javascript">
$(function(){
$('.answerlist').each(function(e){
$(this).click(function(){
var valrad = $("input[#name=answer]:checked").val();
var post_data = {
'ansid': valrad,
'<?php echo $this->security->get_csrf_token_name(); ?>' : '<?php echo $this->security->get_csrf_hash(); ?>'
};
$.ajax({
type: "POST",
url: "<?php echo base_url(); ?>online/checkanswer",
data: post_data,
success: function(msg){
/// do something
}
});
});
});
});
</script>
As others say - you have to post the CSFR token name and its value with the AJAX request parameters. Here is a simple solution to append it automatically to every AJAX request.
Here is what I put on my main view, so this code is on every page before loading the other javascript files:
<script>
var csfrData = {};
csfrData['<?php echo $this->security->get_csrf_token_name(); ?>']
= '<?php echo $this->security->get_csrf_hash(); ?>';
</script>
<!-- ... include other javascript files -->
</body>
</html>
And here is a part of a javascript file that I include on every page:
$(function() {
// Attach csfr data token
$.ajaxSetup({
data: csfrData
});
});
If you want, you can echo both the token name and the hash somewhere appropriate. Something like this.
echo $this->security->get_csrf_token_name()
and
echo $this->security->get_csrf_hash()
Or, you could use form_open() as usual and use the hidden input that is generated for you from your javascript. Disabling the CSRF-functionality is the wrong way to go.
Having reviewed my situation I believe the best option is to use CSRF but reset the token on each attempt. Otherwise the ideas expressed earlier about re-using the cookie token would allow an attacker to resubmit data hundreds of times using the same token which defeats the object of the point.
As such I have created the following function:
public function resetCSRF(){
$this->security = null;
$_COOKIE[$this->config->item('csrf_cookie_name')] = null;
load_class('Security', 'core');
$this->security->csrf_set_cookie();
return $this->security->get_csrf_hash();
}
If for example an ajax based login form fails - call this function in your PHP and then on the javascript side that receives the failure (this solution uses Jquery and a getCookie function from w3schools) would then simply call:
$('input[name="csrf_test_name"]').val(getCookie('csrf_cookie_name'));
Basically what you need to do is get the expected csrf value from the cookie (named 'ci_csrf_token' by default), then post it along with your other data.
You would need to modify this line:
$.post(baseurl + 'ajax/images',{'id' : ID}, function(data) {
to:
$.post(baseurl + 'ajax/images',{'id' : ID,'ci_csrf_token' : $.cookie('ci_csrf_token')}, function(data) {
Might need to install the cookie addon (I'm not really sure; I use mootools). Here is more information: http://aymsystems.com/ajax-csrf-protection-codeigniter-20.
Previous suggestions work great, but rather than using a variable that you can apply in every data-post, I find it simpler to use the ajax-setting to automatically apply this token to every post:
$(document).ajaxSend(function(elm, xhr, s){
if(s.data){
s.data += '&';
}
s.data += '<?php echo $this->security->get_csrf_token_name(); ?>=<?php echo $this->security->get_csrf_hash(); ?>';
});
(works with jquery-1.9.1. I'm not sure about other jquery-versions)
The only problem with a few of the above answers is that a csrf token is only valid for one request, so if you make a post request via ajax and do not refresh the page you will not have the current csrf token for your next ajax post request. This is my solution:
In your CodeIgniter Controller:
$data = array('data'=> 'data to send back to browser');
$csrf = $this->security->get_csrf_hash();
$this->output
->set_content_type('application/json')
->set_output(json_encode(array('data' => $data, 'csrf' => $csrf)));
$data = the data to return to the browser
$csrf = new csrf token to be used by the browser for next ajax post request
Obviously you can output this in other ways but JSON is used mostly with ajax calls. Also include this token in every post response to be used for the next post request
Then in your next ajax request (javascript):
var token = data.csrf;
$.ajax({
url: '/next/ajax/request/url',
type: 'POST',
data: { new_data: 'new data to send via post', csrf_token:token },
cache: false,
success: function(data, textStatus, jqXHR) {
// Get new csrf token for next ajax post
var new_csrf_token = data.csrf
//Do something with data returned from post request
},
error: function(jqXHR, textStatus, errorThrown) {
// Handle errors here
console.log('ERRORS: ' + textStatus + ' - ' + errorThrown );
}
});
Also remember that where I've got csrf_token:token replace crf_token with the name of your token found in application/config/config.php on line that states $config['csrf_token_name'] = 'csrf_token';