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