1

I have a hidden post meta called _payment for my posts. When i was looking into the tables of the wordpress, I noticed that there are tens of this post meta with the same name for the same post! Here is a picture of the database: Multiple postmeta for one post

I don't think I write any wrong code to cause this, I just added and updated the field, but it should update the same field with the same meta_id, not that create a new one with a different meta_id for the same post.

But still I don't know, maybe it's a normal wordpress thing? Or I'm wrong ...

Here are the codes I'm using for modifying this field:

function payment_meta($post_ID)
{
    $user_id = get_post_field( 'post_author', $post_ID );
    $user_role = 'editor'; 
    $post_type = 'portfolio'; 
    if( get_post_type( $post_ID ) == $post_type ) {
        if ( get_post_meta($post_ID, '_payment', true) != '1' && !user_can( $user_id, $user_role )) {
            add_post_meta($post_ID, '_payment', '0');
        }
        else if ( get_post_meta($post_ID, '_payment', true) == '' && user_can( $user_id, $user_role )) {
            add_post_meta($post_ID, '_payment', '1');
        }
    }
}

add_action('wp_insert_post', 'payment_meta', 11, 1);

And this code, this runs a cron job when the a post expires :

function unpublish_post($post_id)
{
    wp_update_post(array(
        'ID' => $post_id,
        'post_status' => 'pending'
    ));

    update_post_meta($post_id, '_payment', '0');
}

add_action('expiration_date', 'unpublish_post', 11, 1);
2
  • How are you using/updating the meta in your code? Aug 9, 2018 at 8:22
  • @jacob-peattie I added the code, if it's not enough, let me know.
    – Amirition
    Aug 9, 2018 at 8:29

1 Answer 1

4

wp_insert_post runs whenever a post is updated, not just when it's first saved. So your payment_meta() function is running every time a post is saved, and since you're using add_post_meta() in that function, a new meta entry is created every time the post is saved.

Instead of using add_post_meta() stick to just using update_post_meta() if a value isn't already set this will still create the meta, but if it already exists it will update the existing value, rather than adding a new one:

function payment_meta($post_ID)
{
    $user_id = get_post_field( 'post_author', $post_ID );
    $user_role = 'editor'; 
    $post_type = 'portfolio'; 
    if( get_post_type( $post_ID ) == $post_type ) {
        if ( get_post_meta($post_ID, '_payment', true) != '1' && !user_can( $user_id, $user_role )) {
            update_post_meta($post_ID, '_payment', '0');
        }
        else if ( get_post_meta($post_ID, '_payment', true) == '' && user_can( $user_id, $user_role )) {
            update_post_meta($post_ID, '_payment', '1');
        }
    }
}

add_action('wp_insert_post', 'payment_meta', 11, 1);
4
  • 1
    One more thing worth noticing is that you should not use user_can with user roles... Aug 9, 2018 at 9:28
  • @krzysiek-dróżdż Yes I can do that, according to the codex : codex.wordpress.org/Function_Reference/user_can
    – Amirition
    Aug 9, 2018 at 19:50
  • @Amirition it's a bug in reference. user_can and current_user_can are both implemented using has_cap and it is clearly stated that "While checking against a role in place of a capability is supported in part, this practice is discouraged as it may produce unreliable results." (developer.wordpress.org/reference/classes/wp_user/has_cap) Aug 9, 2018 at 20:04
  • @krzysiek-dróżdż Since I need to check the role, what is the best function to do that?
    – Amirition
    Aug 10, 2018 at 14:21

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.