Skip to main content
Add updated example function, tidy/trim/reword bits of original answer and update links
Source Link
t31os
  • 18.7k
  • 3
  • 56
  • 68

One possible approach would be to use one of the helper methods in the WPDB classWPDB class to do a more refined meta-based query. The caveat to using some of these functions, however, is that you don't usually get back a simple array of data, and usually have to make needless references to object properties, even if you're only calling for one column or row.

Of course, not all functions are the one and the same, and a purposeful mention goes out toUsing the WPDB method get_col$wpdb which returnsfunction get_col it's possible return a simple flat array of the data queried for, I make this mention specifically because the example following will call upon this method.

WordPress - WPDB Selecting a column of data
$wpdb->get_col()

Here's an example function which queries the database for all posts of a chosenspecified post type, post status and with a specific meta key (or custom field to the less technically minded).

function get_meta_values( $key$meta_key = '', $type$post_type = 'post', $status$post_status = 'publish' ) {
    
    global $wpdb;
    
    if( empty( $key$meta_key ) )
        return;
    
    $r$meta_values = $wpdb->get_col( $wpdb->prepare( "
        SELECT pm.meta_value FROM {$wpdb->postmeta} pm
        LEFT JOIN {$wpdb->posts} p ON p.ID = pm.post_id
        WHERE pm.meta_key = %s 
        AND p.post_statuspost_type = %s 
        AND p.post_typepost_status = %s 
    ", $key$meta_key, $status$post_type, $type$post_status ) );
    
    return $r;$meta_values;
}

So for example, if you would like to find out which posts have a meta key of rating, for the post type movies and you'd like to store that information inside a variable, an example of such a call would be.

If you wanted to do nothinglittle more than print that data to the screen, PHP's implode function can quickly splice that simplecondense the array into lines of dataa string.

You can also use the returned data to work out how many posts have thesethe meta values by doing a simple loopiteration(loop) over the returned data and building an array of the counts, for example.

$movie_ratings = get_meta_values( 'rating', 'movies' );
if( !empty( $movie_ratings ) ) {
    $num_of_ratings = array();[];
    foreach( $movie_ratings as $meta_value ) {
        $num_of_ratings[$meta_value] = ( isset( $num_of_ratings[$meta_value] ) ) ? $num_of_ratings[$meta_value] + 1 : 1;
    }
}

// Output the number of ratings
printf( '<pre>%s</pre>', print_r( $num_of_ratings ) );  

/*
ResultOutput:
Array(
    [5] => 10
    [9] => 2
)
// ie. there are 10 movie posts with a rating of 5 and 2 movie posts with a rating of 9.
*/

This logic could be applied to various kinds of data, and extended to work any number of different ways. So I hope my examples have been helpful and simple enough to follow.


Using transients to cache the results

And here's an updated version that uses WordPress transients to cache the query, as that seems to be the main criticism for using $wpdb in other provided answers.

function get_meta_values( string $meta_key, string $post_type = 'post', bool $distinct = false, string $post_status = 'publish' ) {
    
    global $wpdb, $wp_post_types;
    
    if( !isset( $wp_post_types[$post_type] ) )
        // Existing WP string, it should translate as is
        return __( 'Invalid post type.' ); 
    
    $transient_key = 'get_' . $wp_post_types[$post_type]->name . '_type_meta_values';
   
    $get_meta_values = get_transient( $transient_key );

    if( true === (bool)$get_meta_values )
        return $get_meta_values;
    
    $distinct = $distinct ? ' DISTINCT' : '';
    
    $get_meta_values = $wpdb->get_col( $wpdb->prepare( "
        SELECT{$distinct} pm.meta_value FROM {$wpdb->postmeta} pm 
        LEFT JOIN {$wpdb->posts} p ON p.ID = pm.post_id 
        WHERE pm.meta_key = %s 
        AND p.post_type = %s 
        AND p.post_status = %s 
    ", $meta_key, $post_type, $post_status ) );
    
    set_transient( $transient_key, $get_meta_values, DAY_IN_SECONDS );

    return $get_meta_values;
}

The DAY_IN_SECONDS constant is one of various time in seconds constants setup by WordPress.

Updated argument and variable names to make them more consistent with WordPress naming and also implemented DISTINCT as an optional parameter following the tip from Howdy_McGee in the comments.

One possible approach would be to use one of the helper methods in the WPDB class to do a more refined meta-based query. The caveat to using some of these functions, however, is that you don't usually get back a simple array of data, and usually have to make needless references to object properties, even if you're only calling for one column or row.

Of course, not all functions are the one and the same, and a purposeful mention goes out to the WPDB method get_col which returns a simple flat array of the data queried for, I make this mention specifically because the example following will call upon this method.

WordPress - WPDB Selecting a column of data
$wpdb->get_col()

Here's an example function which queries the database for all posts of a chosen post type, post status and with a specific meta key (or custom field to the less technically minded).

function get_meta_values( $key = '', $type = 'post', $status = 'publish' ) {
    
    global $wpdb;
    
    if( empty( $key ) )
        return;
    
    $r = $wpdb->get_col( $wpdb->prepare( "
        SELECT pm.meta_value FROM {$wpdb->postmeta} pm
        LEFT JOIN {$wpdb->posts} p ON p.ID = pm.post_id
        WHERE pm.meta_key = %s 
        AND p.post_status = %s 
        AND p.post_type = %s
    ", $key, $status, $type ) );
    
    return $r;
}

So for example, if you like to find out which posts have a meta key of rating, for the post type movies and you'd like to store that information inside a variable, an example of such a call would be

If you wanted to do nothing more than print that data to the screen, PHP's implode function can quickly splice that simple array into lines of data.

You can also use the returned data to work out how many posts have these meta values by doing a simple loop over the returned data and building an array of the counts, for example.

$movie_ratings = get_meta_values( 'rating', 'movies' );
if( !empty( $movie_ratings ) ) {
    $num_of_ratings = array();
    foreach( $movie_ratings as $meta_value )
        $num_of_ratings[$meta_value] = ( isset( $num_of_ratings[$meta_value] ) ) ? $num_of_ratings[$meta_value] + 1 : 1;
}

/*
Result:
Array(
    [5] => 10
    [9] => 2
)
// ie. there are 10 movie posts with a rating of 5 and 2 movie posts with a rating of 9.
*/

This logic could be applied to various kinds of data, and extended to work any number of different ways. So I hope my examples have been helpful and simple enough to follow.

One possible approach would be to use one of the helper methods in the WPDB class to do a more refined meta-based query.

Using the $wpdb function get_col it's possible return a simple flat array of data.

Here's an example function which queries the database for all posts of a specified post type, post status and meta key (or custom field to the less technically minded).

function get_meta_values( $meta_key = '', $post_type = 'post', $post_status = 'publish' ) {
    
    global $wpdb;
    
    if( empty( $meta_key ) )
        return;
    
    $meta_values = $wpdb->get_col( $wpdb->prepare( "
        SELECT pm.meta_value FROM {$wpdb->postmeta} pm
        LEFT JOIN {$wpdb->posts} p ON p.ID = pm.post_id
        WHERE pm.meta_key = %s 
        AND p.post_type = %s 
        AND p.post_status = %s 
    ", $meta_key, $post_type, $post_status ) );
    
    return $meta_values;
}

So for example, if you would like to find out which posts have a meta key of rating, for the post type movies and to store that information inside a variable, an example of such a call would be.

If you wanted to do little more than print that data to the screen, PHP's implode function can quickly condense the array into a string.

You can also use the returned data to work out how many posts have the meta values by doing a simple iteration(loop) over the returned data and building an array of the counts, for example.

$movie_ratings = get_meta_values( 'rating', 'movies' );
if( !empty( $movie_ratings ) ) {
    $num_of_ratings = [];
    foreach( $movie_ratings as $meta_value ) {
        $num_of_ratings[$meta_value] = isset( $num_of_ratings[$meta_value] ) ? $num_of_ratings[$meta_value] + 1 : 1;
    }
}

// Output the number of ratings
printf( '<pre>%s</pre>', print_r( $num_of_ratings ) );  

/*
Output:
Array(
    [5] => 10
    [9] => 2
)
ie. there are 10 movie posts with a rating of 5 and 2 movie posts with a rating of 9.
*/

This logic could be applied to various kinds of data, and extended to work any number of different ways. So I hope my examples have been helpful and simple enough to follow.


Using transients to cache the results

And here's an updated version that uses WordPress transients to cache the query, as that seems to be the main criticism for using $wpdb in other provided answers.

function get_meta_values( string $meta_key, string $post_type = 'post', bool $distinct = false, string $post_status = 'publish' ) {
    
    global $wpdb, $wp_post_types;
    
    if( !isset( $wp_post_types[$post_type] ) )
        // Existing WP string, it should translate as is
        return __( 'Invalid post type.' ); 
    
    $transient_key = 'get_' . $wp_post_types[$post_type]->name . '_type_meta_values';
   
    $get_meta_values = get_transient( $transient_key );

    if( true === (bool)$get_meta_values )
        return $get_meta_values;
    
    $distinct = $distinct ? ' DISTINCT' : '';
    
    $get_meta_values = $wpdb->get_col( $wpdb->prepare( "
        SELECT{$distinct} pm.meta_value FROM {$wpdb->postmeta} pm 
        LEFT JOIN {$wpdb->posts} p ON p.ID = pm.post_id 
        WHERE pm.meta_key = %s 
        AND p.post_type = %s 
        AND p.post_status = %s 
    ", $meta_key, $post_type, $post_status ) );
    
    set_transient( $transient_key, $get_meta_values, DAY_IN_SECONDS );

    return $get_meta_values;
}

The DAY_IN_SECONDS constant is one of various time in seconds constants setup by WordPress.

Updated argument and variable names to make them more consistent with WordPress naming and also implemented DISTINCT as an optional parameter following the tip from Howdy_McGee in the comments.

One possible approach would be to use one of the helper methods in the WPDB class to do a more refined meta based-based query. The caveat to using some of these functions, however, is that you don't usually get back a simple array of data, and usually have to make needless references to object properties, even if you're only calling for one column or row.

Of course, not all functions are the one and the same, and a purposeful mention goes out to the WPDB method, get_col which returns a simple flat array of the data queried for, iI make this mention specifically because the example following will call upon this method.

So for example, if you like to find out which posts have a meta key of rating, for the post type movies and you'd like to store that information inside a variable, an example of such a call would be..

If you wanted to do nothing more than print that data to the screen, PHP's implodeimplode function can quickly splice that simple array into lines of data.

// Print the meta values seperateseparated by a line break
echo implode( '<br />', get_meta_values( 'YOURKEY' ));

This logic could be applied to various kinds of data, and extended to work any number of different ways. So iI hope my examples have been helpful and simple enough to follow.

One possible approach would be to use one of the helper methods in the WPDB class to do a more refined meta based query. The caveat to using some of these functions however, is that you don't usually get back a simple array of data and usually have to make needless references to object properties, even if you're only calling for one column or row.

Of course, not all functions are the one and the same, and a purposeful mention goes out to the WPDB method, get_col which returns a simple flat array of the data queried for, i make this mention specifically because the example following will call upon this method.

So for example, if you like to find out which posts have a meta key of rating, for the post type movies and you'd like to store that information inside a variable, an example of such a call would be..

If you wanted to do nothing more than print that data to screen, PHP's implode function can quickly splice that simple array into lines of data.

// Print the meta values seperate by a line break
echo implode( '<br />', get_meta_values( 'YOURKEY' ));

This logic could be applied to various kinds of data, and extended to work any number of different ways. So i hope my examples have been helpful and simple enough to follow.

One possible approach would be to use one of the helper methods in the WPDB class to do a more refined meta-based query. The caveat to using some of these functions, however, is that you don't usually get back a simple array of data, and usually have to make needless references to object properties, even if you're only calling for one column or row.

Of course, not all functions are the one and the same, and a purposeful mention goes out to the WPDB method get_col which returns a simple flat array of the data queried for, I make this mention specifically because the example following will call upon this method.

So for example, if you like to find out which posts have a meta key of rating, for the post type movies and you'd like to store that information inside a variable, an example of such a call would be

If you wanted to do nothing more than print that data to the screen, PHP's implode function can quickly splice that simple array into lines of data.

// Print the meta values separated by a line break
echo implode( '<br />', get_meta_values( 'YOURKEY' ));

This logic could be applied to various kinds of data, and extended to work any number of different ways. So I hope my examples have been helpful and simple enough to follow.

Change '%s' tot %s or else the string will be double escaped
Source Link
function get_meta_values( $key = '', $type = 'post', $status = 'publish' ) {
    
    global $wpdb;
    
    if( empty( $key ) )
        return;
    
    $r = $wpdb->get_col( $wpdb->prepare( "
        SELECT pm.meta_value FROM {$wpdb->postmeta} pm
        LEFT JOIN {$wpdb->posts} p ON p.ID = pm.post_id
        WHERE pm.meta_key = '%s'%s 
        AND p.post_status = '%s'%s 
        AND p.post_type = '%s'%s
    ", $key, $status, $type ) );
    
    return $r;
}
function get_meta_values( $key = '', $type = 'post', $status = 'publish' ) {
    
    global $wpdb;
    
    if( empty( $key ) )
        return;
    
    $r = $wpdb->get_col( $wpdb->prepare( "
        SELECT pm.meta_value FROM {$wpdb->postmeta} pm
        LEFT JOIN {$wpdb->posts} p ON p.ID = pm.post_id
        WHERE pm.meta_key = '%s' 
        AND p.post_status = '%s' 
        AND p.post_type = '%s'
    ", $key, $status, $type ) );
    
    return $r;
}
function get_meta_values( $key = '', $type = 'post', $status = 'publish' ) {
    
    global $wpdb;
    
    if( empty( $key ) )
        return;
    
    $r = $wpdb->get_col( $wpdb->prepare( "
        SELECT pm.meta_value FROM {$wpdb->postmeta} pm
        LEFT JOIN {$wpdb->posts} p ON p.ID = pm.post_id
        WHERE pm.meta_key = %s 
        AND p.post_status = %s 
        AND p.post_type = %s
    ", $key, $status, $type ) );
    
    return $r;
}
Improve the answer(hopefully)
Source Link
t31os
  • 18.7k
  • 3
  • 56
  • 68
Loading
Source Link
t31os
  • 18.7k
  • 3
  • 56
  • 68
Loading