$conf, $runtime; function_exists('chdir') AND chdir(APP_PATH); $r = 'mysql' == $conf['cache']['type'] ? website_set('runtime', $runtime) : cache_set('runtime', $runtime); } function runtime_truncate() { global $conf; 'mysql' == $conf['cache']['type'] ? website_set('runtime', '') : cache_delete('runtime'); } register_shutdown_function('runtime_save'); ?>Update status, meta while inside a post using AJAX button|Programmer puzzle solving
最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

Update status, meta while inside a post using AJAX button

matteradmin9PV0评论

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;

}

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;

}
Share Improve this question asked Mar 6, 2019 at 8:51 samjco-comsamjco-com 5996 silver badges19 bronze badges 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
Add a comment  | 

1 Answer 1

Reset to default 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();
}
Post a comment

comment list (0)

  1. No comments so far