1

For some reason, I have to unpublish certain posts every time wordpress loads. This is my code:

function af_change_post_status() {
    $notpayed_posts = new WP_Query( array(
        'meta_key'                  =>  '_payment',
        'meta_value'                =>  '0'
    ) );

    foreach ($notpayed_posts as $notpayed_post) {
        wp_transition_post_status( 'draft', $notpayed_post->post_status, $notpayed_post);
    }
}
add_action( 'init', 'af_change_post_status' );

The query is correct and it's returning the posts I want, but the wp_transition_post_status function is not working and I don't know why?

2

This function contains do_action() calls for post status transition action hooks. The order of the words in the function name might be confusing – it does not change the status of posts, it only calls actions that can be hooked into by plugin developers.

https://codex.wordpress.org/Function_Reference/wp_transition_post_status

What you want is wp_update_post, you're also using WP_Query incorrectly:

``` $notpayed_posts = new WP_Query( array( 'meta_key' => '_payment', 'meta_value' => '0' ) );

while ($notpayed_posts->have_posts()) {
    $notpayed_posts->the_post();
    wp_update_post( array(
        'ID' => get_the_ID(),
        'post_status' => 'draft'
    ));
}
wp_reset_postdata();

Also, keep in mind that your query is an expensive/very slow post meta query, post meta isn't built for searching or queries where you're looking for posts. Consider a taxonomy term.

You also do nothing to change the meta afterwards, so if there are 10 posts that match, then every page load will try to update 10 posts, even if they've already been updated! Either change the meta value with update_post_meta or check the post status in the query, e.g.

$notpayed_posts = new WP_Query( array(
    'post_status'               =>  'publish',
    'meta_key'                  =>  '_payment',
    'meta_value'                =>  '0'
) );

Additionally, use a cron job, don't do it on every page load by using the init hook, it's very bad for performance and incompatible with page caching

  • Thank you for the good answer, wp_update_post first parameter was not in the codex though. – Amirition Jul 14 '18 at 14:00
  • @Amirition you're right, it needs to be an ID parameter in the array as shown in the example. Note that wp_update_post is a thin wrapper around wp_insert_post which can also be used to modify existing posts – Tom J Nowell Jul 14 '18 at 14:26
1

It's pretty simple error. You use WP_Query to get posts, but then you try to use that WP_Query object as an array, but this class doesn't implement iterator, AFAIR.

function af_change_post_status() {
    $notpayed_posts = new WP_Query( array(
        'meta_key'                  =>  '_payment',
        'meta_value'                =>  '0'
    ) );

    foreach ($notpayed_posts->posts as $notpayed_post) {
        wp_transition_post_status( 'draft', $notpayed_post->post_status, $notpayed_post);
    }
}
add_action( 'init', 'af_change_post_status' );

This should work better (if your query is correct).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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