Question

So I am trying to click a custom button I made in a meta box the fire off AJAX. All works except getting the ID of the post and the refreshing of the page. I have tried using global $post; $post_id = $post->ID or $post_id = $_POST['post_id']; or $post_id = get_the_ID(); , none of these work.

What I was trying to accomplish eventually is: after clicking the button, a popup happens with "are you sure?"Yes/No. If I click Yes, to change Status function fires and refreshes the post page with status changed.

I am using an Ajax Get with the URL of behind my button: /wp-admin/admin-ajax.php?action=ew_change_status

Reference: Trying to load content of a post via AJAX

This is my functions.php code:

add_action( 'wp_ajax_change_status', 'ew_change_status' );


function ew_change_status() {

    //$post_id = $_POST['post_id'];
    //$post_id = get_the_ID();

    global $post; 
    global $user_ID; 

    $post_id = $post->ID;
    var_dump($post_id);

    remove_filter( current_filter(), __FUNCTION__ );

   //Show popup
   // ...

   // Update Status
  $my_post = array(
      'ID'           => $post_id,
      'post_status'   => 'status-pending',
  );

   // Update custom field with User Id      
   update_post_meta($post_id, 'post_key', $user_ID);

   //echo "Updated";

   // Update the post into the database
   wp_update_post( $my_post );

    //wp_redirect(); //Same Page?
    //exit;

}
Was it helpful?

Solution

First things first

In a wp_ajax_{action} or wp_ajax_nopriv_{action} callback, the global $post variable is by default a null because WordPress has not yet set it up. You can confirm it using a simple callback like so:

add_action( 'wp_ajax_test', function(){
    global $post;
    var_dump( $post );
    wp_die();
} );

Visit /wp-admin/admin-ajax.php?action=test and you should see NULL displayed on the page. If you don't see a NULL, then it's possible that a plugin or custom code has made a query which changed the $post variable.

Now a solution

Since you're making the AJAX request via a button click and the button is inside a meta box which I suppose is on the post edit screen (wp-admin/edit.php), then an easy way to fix the issue of the $post being still a NULL in your wp_ajax_change_status callback, is to send the post ID from your AJAX script (JavaScript).

On the post edit screen, the post ID is stored in a hidden input field named post_ID which looks like this and stores the ID of the post that's currently being edited:

<input type='hidden' id='post_ID' name='post_ID' value='123' />

So you can use the value and send it to your AJAX callback. E.g.:

jQuery.ajax({
    url: '/wp-admin/admin-ajax.php',
    data: {
        action:  'change_status',
        post_id: jQuery( '#post_ID' ).val() // send the post ID
    },
    type: 'post'
});

Then in your AJAX callback (i.e. the ew_change_status() function), you can retrieve the submitted post ID like so:

$post_id = filter_input( INPUT_POST, 'post_id' );

Additional Notes

  1. In your AJAX callback, make sure to check whether the current user can edit the post. E.g.:

    if ( ! current_user_can( 'edit_post', $post_id ) ) {
        wp_die();
    }
    
  2. Use a nonce (because you are editing a post). For example,

    a) In your meta box, create a hidden input for storing the nonce:

    // Creates an <input> with the `id` and `name` "my_security".
    <?php wp_nonce_field( 'change-post-status', 'my_security' ); ?>
    

    b) Include the nonce in the AJAX request:

    jQuery.ajax({
        url: '/wp-admin/admin-ajax.php',
        data: {
            action:  'change_status',
            post_id:  jQuery( '#post_ID' ).val(),
            security: jQuery( '#my_security' ).val()
        },
        type: 'post'
    });
    

    c) In your AJAX callback, verify the nonce:

    check_ajax_referer( 'change-post-status', 'security' );
    

So your ew_change_status() may look like:

function ew_change_status() {
    check_ajax_referer( 'change-post-status', 'security' );

    $post_id = filter_input( INPUT_POST, 'post_id' );
    if ( ! $post_id || ! ( $post = get_post( $post_id ) ) ) {
        wp_die( 'No such post, or invalid ID.' );
    }

    if ( ! current_user_can( 'edit_post', $post_id ) ) {
        wp_die( 'You can not edit this post.' );
    }

    ... your code here ...

    wp_die();
}
Licensed under: CC-BY-SA with attribution
Not affiliated with wordpress.stackexchange
scroll top