Search code examples
phpwordpresscontent-typetimber

Wordpess Timber - combine $context to get two post-types?


On my homepage I would like to show the most recent new items (standard Wordpress 'posts') OR events (custom post-type) in date order. I have the following bringing in each content-type, but what I get is all the events in date order; followed by all the news items in date order - what I want is News OR Events in date order, so if the newest item is an Event, then that's what comes first, followed by a News item, followed be an Event if necessary and so on. I assume there's some way to combine the context?

<?php

$context          = Timber::context();
$context['home_page_content'] = new Timber\PostQuery('post_type=vopthomepage');

// below are the two I want to combine

$eventArgs  =   array(
'post_type'         =>  'mec-events',
'posts_per_page'    =>  -1,
'orderby'           =>  array(
'date'              =>  'DESC'
));
$context['mec_events'] = new Timber\PostQuery($eventArgs);

$postArgs   =   array(
    'post_type'     =>  'post',
    'posts_per_page'=>  -1,
    'category_name' =>  'featured',
    'orderby'       =>  array(
    'date'          =>  'DESC'
));
$context['featured_items'] = new Timber\PostQuery($postArgs);

Timber::render( 'index.twig', $context );

Any help greatly appreciated!


Solution

  • If you wanted to combine the two queries and then sort them, you could first merge the query results into a single array that you then sort with wp_list_sort().

    <?php
    
    $context = Timber::context();
    
    $context['home_page_content'] = new Timber\PostQuery('post_type=vopthomepage');
    
    $eventArgs = [
        'post_type'      => 'mec-events',
        'posts_per_page' => 10,
        'orderby'        => [
            'date' => 'DESC',
        ],
    ];
    
    $postArgs = [
        'post_type'      => 'post',
        'posts_per_page' => 10,
        'category_name'  => 'featured',
        'orderby'        => [
            'date' => 'DESC',
        ],
    ];
    
    $events         = new Timber\PostQuery( $eventArgs );
    $featured_items = new Timber\PostQuery( $postArgs );
    
    $posts = array_merge( $events->get_posts(), $featured_items->get_posts() );
    $posts = wp_list_sort( $posts, 'post_date', 'DESC' );
    
    // Restrict to certain amount of items.
    $posts = array_slice( $posts, 0, 6 );
    
    $context['posts'] = $posts;
    
    Timber::render( 'index.twig', $context );
    

    You can then loop through that custom-built posts array in Twig

    {% for post in posts %}
        {# Display post teaser #}
    {% endfor %}
    

    What I would do is restrict the amount of posts that you fetch for each of the queries.

    This works well if the amount of published posts and events are about the same over time. However, you could end with only events or posts showing up, if the newest posts are only from one type.

    To work around that, you could e.g. only fetch 3 posts of each post types to make it a total of 6. You could still use wp_list_sort(), but that way you would have at least 3 of each post types displayed.

    You could also try to use more than one post type for the post_type argument in WP_Query – it accepts an array of post types, but I guess that wouldn’t work if you only want to include posts from the featured category.