5

I'm trying to create an email signup form with an AJAX request.

Early on I found that Wordpress empties the $_POST variable by default. I tried using admin_post and admin_post_nopriv but neither of those seemed to be working. I'm now trying the following:

add_action('wp_ajax_nopriv_newsletter', 'subscribeToNewsletter');
add_action('wp_ajax_newsletter', 'subscribeToNewsletter');

function subscribeToNewsletter()
{

  echo json_encode([ 'success' => true ]);

In my JavaScript, if I use the following:

axios
  .post('/wp-admin/admin-ajax.php', {
    'email' : '[email protected]',
    'action' : 'newsletter',
  })
  .then(response => {
    console.log(response.data);
  });

I get a 400 bad request and a 0 returned. If I change it to:

axios
  .get('/wp-admin/[email protected]&action=newsletter')
  .then(response => {
    console.log(response.data);
  });

everything works.

Can admin-ajax.php not handle POST requests? I don't want to use a GET request* for subscribing someone to a newsletter, and I'd like to do it over AJAX.


*From W3 schools (which normally I hate but has a good overview on requests):

Some other notes on GET requests:

  • GET requests can be cached
  • GET requests remain in the browser history
  • GET requests can be bookmarked
  • GET requests should never be used when dealing with sensitive data
  • GET requests have length restrictions
  • GET requests is only used to request data (not modify)

1 Answer 1

13

The issue here, I think, is how axios works. Not WordPress. But you're absolutely correct to want to use a POST request here.

By default I believe axios sends data in a POST request as JSON in the body. To get JSON in the body of the request in PHP you need to do this (from here):

$inputJSON = file_get_contents('php://input');
$input = json_decode($inputJSON, TRUE); //convert JSON into array

The problem with that is that for the wp_ajax_ hooks to work, WordPress looks for the action in $_REQUEST['action']. This won't be set if the action name is part of the request body, since $_REQUEST isn't populated when the data is sent as JSON.

I believe that if you want to send POST data in axios the way a form does, and access it with $_POST or $_REQUEST, then you need to send it as FormData in the script:

var data = new FormData();

data.append('email', '[email protected]');
data.append('action', 'newsletter');

axios
    .post('/wp-admin/admin-ajax.php', data)
    .then(response => {
        console.log(response.data);
    });

PS: Just so you're aware, this syntax: response => {, won't work in any version of IE.

1
  • Wow, that's a fantastic insight. Can confirm everything you said. This has tripped me up multiple times in the past, I'm thrilled to have it all working now –thanks. Commented Jun 28, 2018 at 11:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.