0

Is it possible to have one query calling one post from each category?

Example:

one query calling:

one post from category one one post from category two one post from category tree

If this is not possible, do I have to make 3 queries?

6
  • It's not possible using WP_Query or get_posts(), but you can do it with a more 'custom' query, using $wpdb, which allows you to enter actual SQL - codex.wordpress.org/Class_Reference/wpdb
    – Dan.
    Commented Nov 28, 2016 at 16:27
  • Well, you could use WP_Query in conjunction with a filter like pre_get_posts, but I think $wpdb is gonna be neater/easier to read
    – Dan.
    Commented Nov 28, 2016 at 16:28
  • Agree it's not possible with one query. I'd use 3, and cache the result in a transient.
    – vancoder
    Commented Nov 28, 2016 at 16:58
  • @vancoder If so (cache the result of each query in a transient), how can I make sure that I always get the latest posts whenever I publish a new one on each category?
    – bpy
    Commented Nov 28, 2016 at 17:21
  • 1
    Possible duplicate of Using WP_Query to Query Multiple Categories with Limited Posts Per Category?
    – cjbj
    Commented Nov 28, 2016 at 20:19

1 Answer 1

0

You can create your own function to return posts objects from different categories using the get_object_in_term() function with some customization on the sql request. This function has only one filter (order).

I know that you seem to want a one time WP_Query, but it can give you some idea.

In this example, I directly set an array of term_id and the args (you can add the order parameter, loop through the term_ids instead of directly set the first parameter of the custom function (I needed to randomize each category).

    $term_ids = array(15,11,24);
    $taxonomies = 'product_cat';
    $args = array(
        'global_limit'=>25,
        'posts_per_page'=>1
    );
    foreach ($term_ids as $term_id){
        $terms_object = get_objects_in_term_with_limit( $term_id, $taxonomies, $args ) ;
        foreach ($terms_object as $object){
            $post = get_post($object);
            $post_object[] = array('ID'=>$post->ID, 'post_title'=> $post->post_title, 'term_id'=>$term_id);
        }
    }
    echo json_encode($post_object);

    function get_objects_in_term_with_limit( $term_ids, $taxonomies, $args = array() ) {
        global $wpdb;

        if ( ! is_array( $term_ids ) ) {
            $term_ids = array( $term_ids );
        }
        if ( ! is_array( $taxonomies ) ) {
            $taxonomies = array( $taxonomies );
        }
        foreach ( (array) $taxonomies as $taxonomy ) {
            if ( ! taxonomy_exists( $taxonomy ) ) {
                return new WP_Error( 'invalid_taxonomy', __( 'Invalid taxonomy.' ) );
            }
        }

        $defaults = array( 'order' => 'ASC', 'posts_per_page'=>5, 'global_limit'=>25 );
        $args = wp_parse_args( $args, $defaults );

        $order = ( 'desc' == strtolower( $args['order'] ) ) ? 'DESC' : 'ASC';

        $global_limit = 'LIMIT '. $args['global_limit'];
        $limit = 'BY RAND() LIMIT '. $args['posts_per_page'];

        $term_ids = array_map('intval', $term_ids );

        $taxonomies = "'" . implode( "', '", array_map( 'esc_sql', $taxonomies ) ) . "'";
        $term_ids = "'" . implode( "', '", $term_ids ) . "'";

        $object_ids = $wpdb->get_col("(SELECT tr.object_id FROM $wpdb->term_relationships AS tr 
              INNER JOIN $wpdb->term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id 
              WHERE tt.taxonomy IN ($taxonomies) AND tt.term_id IN ($term_ids) 
              ORDER BY tr.object_id $order $global_limit) 
              ORDER $limit");

        if ( ! $object_ids ){
            return array();
        }
        return $object_ids;
    }

Hope it helps and that saves your time.

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.