0

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;

}
5
  • If you're making the AJAX request to the wp-admin/admin-ajax.php, the $post object is null and so does get_queried_object(), because there's no queried object - unlike for example, when loading a post page, the queried object is a post. So you might want to send the post ID from your AJAX script (JS).
    – Sally CJ
    Commented Mar 6, 2019 at 9:54
  • Well. If I use admin_notices action it seems to work somewhat.
    – samjco-com
    Commented Mar 6, 2019 at 9:57
  • Because admin_notices is fired later; but the wp_ajax_xxx is fired earlier before the $post is setup. Try var_dump( did_action( 'admin_notices' ) ); from the wp_ajax_xxx callback.
    – Sally CJ
    Commented Mar 6, 2019 at 10:09
  • IS there another hook I could use?
    – samjco-com
    Commented Mar 11, 2019 at 7:33
  • Check my answer. I hope it helps.
    – Sally CJ
    Commented Mar 11, 2019 at 15:03

1 Answer 1

1

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();
}

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.