Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

This is related to this other question, I tried with get_posts, pre_get_posts, WP_Query and basically every option I could find for 2 days now, no solution yet.

The full problem in hand: I have 2 post-types, articles and news. A post from "news" can be "featured" or "non-featured". I need to query 1 featured news, 4 articles and 2 non-featured news, and display them on a page in that order. The page uses the page-mypage.php template.

The posts need to be in that specific order because the size of the post changes depending on the type and the "featured" meta option. My grid is using Masonry and the sequence that works to have a full grid (no holes or weird empty space) is featured, article, article, article, article, non-featured, non-featured.

With the get_posts approach in the other question I can't get the pagination working. It works when navigating to /page/X but I tried a bunch of custom pagination solutions that didn't work and paginate_links which I couldn't get to work either.

So now I'm thinking of using a regular WP_Query but how do I tell WordPress I want that many posts from each post-type and in that particular order?

Here's what I really want to do but I can't seem to find a way to do it with WP_Query to make pagination work properly (damn pagination!):

$articles = get_posts(array(
  'post_type' => 'articles',
  'numberposts' => 4
));

$featured = get_posts(array(
  'post_type' => 'news',
  'numberposts' => 1,
  'meta_query' => array(
    array(
      'key' => 'featured-news',
      'value' => 'Yes',
      'compare' => 'LIKE'
    )
  )
));

$non_featured = get_posts(array(
  'post_type' => 'news',
  'numberposts' => 2,
  'meta_query' => array(
    array(
      'key' => 'featured-news',
      'value' => 'No',
      'compare' => 'LIKE'
    )
  )
));

// Merge in the order I need them to appear
$all_posts = array_merge($featured, $articles, $non-featured);

// The loop

Halp!.

share|improve this question

1 Answer 1

up vote 0 down vote accepted

You can use WP_Query() with paged array key to pass the current page number:

<?php
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$args = array(
        'post_type' => 'articles',
        'posts_per_page' => 4,
        'paged' => $paged
    );
$articles = new WP_Query($args);
////////////////////////////////
$args = array(
        'post_type' => 'news',
        'posts_per_page' => 1,
        'meta_query' => array(
            array(
                'key' => 'featured-news',
                'value' => 'Yes',
                'compare' => 'LIKE'
            )
        ),
        'paged' => $paged
    );
$featured = new WP_Query($args);
////////////////////////////////
$args = array(
        'post_type' => 'news',
        'posts_per_page' => 2,
        'meta_query' => array(
            array(
                'key' => 'featured-news',
                'value' => 'No',
                'compare' => 'LIKE'
            )
        ),
        'paged' => $paged
    );
$non_featured = new WP_Query($args);
////////////////////////////////
$articles = objectToArray($articles); // objectToArray() function defines below
$featured = objectToArray($featured);
$non_featured = objectToArray($non_featured);
$all_posts = array_merge($featured, $articles, $non_featured);
?>

And because you are query-ing from 3 post types, pagination will fail, because it doesn't know from which post type pagination should be based on!

You can use a manual pagination:

<?php
// $paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
if($paged > 1)
{
    echo "<a href=\"".home_url('/')."/page/".($paged-1)."\">Previous page</a>";
}
echo "<a href=\"".home_url('/')."/page/".($paged+1)."\">Next page</a>";
?>

Maybe you want change the HREF attr to something else.

Which I forgot:

<?php
    function objectToArray($d) {
        if (is_object($d)) {
            $d = get_object_vars($d);
        }
        if (is_array($d)) {
            return array_map(__FUNCTION__, $d);
        }
        else {
            return $d;
        }
    }
?>

WP_Query returns a stdClass Object, first you should convert it to an array like below:

<?php
    $articles = objectToArray($articles);
    $featured = objectToArray($featured);
    $non_featured = objectToArray($non_featured);
?>

Then merging them. (updated code above)

Updated

Another handy way is merging stdClass Objects: http://stackoverflow.com/a/1953077/1906508

share|improve this answer
    
Mmmm, are you sure you can merge WP_Query objects like that. I tried something like this already. I'm using Pagenavi but I'll have a look at the custom pagination. –  elclanrs Mar 22 '13 at 8:18
    
@elclanrs updated my post. –  revo Mar 22 '13 at 8:40
    
Now that looks better, but what's the point of using WP_Query if I end up using a foreach with an array? I could also merge posts without objectToArray like this I guess: $all = array_merge($articles->posts, $featured->posts, $non_featured->posts). –  elclanrs Mar 22 '13 at 8:45
    
@elclanrs that's your force! i don't know which method u care and u want to show the results, but u want posts_per_page argument different for each post_type. Also you'd better see this : wordpress.stackexchange.com/questions/71576/… Also I added a link at the end of my answer. –  revo Mar 22 '13 at 8:56
    
I end up not doing this after all, found a better solution with Masonry. The pagination helped tho. Thanks. –  elclanrs Mar 23 '13 at 7:35

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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