I'm developing a simple WordPress plugin as part of my WordPress learning. It's about bulk post approval. The full plugin code is given in this question: Bulk post approval and publishing doesn't work.

The plugin works the way I want it to, but I'm now trying to improve it.

For example, the following function is part of the plugin code:

function karma_get_pre_publish_posts() {
    // get all draft posts with 'approve' custom field set to 'pre-publish'
    $args = array(
        'post_type' => 'post',
        'post_status' => 'draft'
    $approval_posts = array();
    $draft_posts = get_posts( $args );
    foreach ( $draft_posts as $post ) {
        if( get_post_meta( $post->ID, 'approve', true ) == 'pre-publish' ) {
            $approval_posts[] = $post;
    return $approval_posts;

It gets all the draft posts using get_posts function, and then checks for all the posts that has post meta approve set to 'pre-publish' using get_post_meta function.

The function works, but I was thinking: if I have many such posts, say 100, then the code will basically run get_post_meta function 100 times. I'm assuming WordPress runs SQL queries in the background every time I use get_post_meta function. This doesn't look very efficient.

I can probably run a single SQL join query like this post to get all the necessary post data, but I'm wondering if there is a more standard way of doing the same in WordPress.

Any suggestions? Any related documentation link would be helpful too.

1 Answer 1


You can use the post meta arguments that get_posts function already supports. So, there is no need to use get_post_meta function in a PHP loop.

For your use case, post meta related arguments can be used in one of the two possible ways:

  1. Either using meta_key, meta_value, meta_compare arguments;

  2. Or, using the meta_query argument which supports an array of different post meta checks and hence is more powerful.

Using any of these methods returns all the necessary post data in one go.


The following example uses meta_key, meta_value, meta_compare arguments to achieve what you want:

function karma_get_pre_publish_posts() {
    $args = array(
        'post_type'    => 'post',
        'post_status'  => 'draft',
        'meta_key'     => 'approve',
        'meta_value'   => 'pre-publish',
        'meta_compare' => '='

    return get_posts( $args );


The meta_query argument on the other hand requires an array of one or more argument arrays to query the posts with related post meta.

Like this:

function karma_get_pre_publish_posts() {
    // Yes, $meta_query argument has to be coded as an array of arrays.
    $meta_query = array(
            'key' => 'approve',
            'value' => 'pre-publish',
            'compare' => '='
    $args = array(
        'post_type' => 'post',
        'post_status' => 'draft',
        'meta_query' => $meta_query

    return get_posts( $args );

Further reading:

  • Post meta related arguments (or parameters) of the get_posts function come from the parse_query method of WP_Query class. You may check the parse_query method documentation for more details.

  • Also, since the internal implementation related to post meta arguments is using the WP_Meta_Query class, you will also find some details in WP_Meta_Query class and WP_Meta_query constructor documentations.

There are user contributed examples in these documentations with more advanced use cases, including multiple post meta comparisons in a single query.

  • Excellent! Thanks a lot.
    – Karma
    Feb 5, 2023 at 14:55

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.