Question:

Categories with post from child categories on front page

Benjamin: 2 weeks ago

I am developing my first WordPress site and I am using the Customizr (https://wordpress.org/themes/customizr/) theme. I need to build a front page, that shows the latest posts from 2 categories - News and Events and all their child categories. So my category tree looks like this:

Articles

-News

--First news child category

--Second news child category

-Events

--First events child category

--Second events child category

and I want the front page to show the category News and the category Events with all the posts in their child categories packed in 2 containers with the headlines News and Events respectively. I am a total newbie in WordPress and I've searched for days for a solution, but I think I'm searching with the wrong keywords, because I didn't found what I need. I've created a child theme, and I'm currently trying to make an index.php with The Loop to achieve that. I've also tried making a static front page which uses a different template.

So which is the right way to do that? Can you please at least give me some pointers? Thank you!

Answer:
Maya: 2 weeks ago

Normally you'd use the pre_get_posts filter for this, but for your specific case, since you probably want to customize how the posts are displayed (separately), I'd recommend setting a static front page and using a shortcode in the content that uses get_posts (https://codex.wordpress.org/Function_Reference/get_posts) (yet this also means that your theme's "Blog" template won't be used.)

eg.

add_shortcode('custom_news_and_events','my_custom_news_and_events');

function my_custom_news_and_events() {
    $news = get_posts(array('category'=>'1','posts_per_page'=>'7'));
    $childnews1 = get_posts(array('category'=>'2','posts_per_page'=>'3'));
    $childnews2 = get_posts(array('category'=>'3','posts_per_page'=>'3'));
    $events = get_posts(array('category'=>'4','posts_per_page'=>'7'));
    $childevents1 = get_posts(array('category'=>'5','posts_per_page'=>'3'));
    $childevents2 = get_posts(array('category'=>'6','posts_per_page'=>'3'));

    $output = '<div id="frontpagenews">';
    $output .= '<h3>News</h3>';
    if (count($childnews1) > 0)) {foreach $news as $post) {
        $output .= custom_post_display($post);
    } }
    $output .= '<h4>Child News 1</h4>';
    if (count($childnews1) > 0)) {foreach $childnews1 as $post) {
        $output .= custom_post_display($post);
    } }
    $output .= '<h4>Child News 2</h4>';
    if (count($childnews2) > 0)) {foreach $childnews2 as $post) {
        $output .= custom_post_display($post);
    } }
    $output .= '</div>';

    $output = '<div id="frontpageevents">';
    $output .= '<h3>Events</h3>';
    if (count($events) > 0)) {foreach $events as $post) {
        $output .= custom_post_display($post);
    } }
    $output .= '<h4>Child Events 1</h4>';
    if (count($childevents1) > 0)) {foreach $childevents1 as $post) {
        $output .= custom_post_display($post);
    } }
    $output .= '<h4>Child Events 2</h4>';
    if (count($childevents2) > 0)) {foreach $childevents2 as $post) {
        $output .= custom_post_display($post);
    } }
    $output .= '</div>';
    return $output;
}

(setting the correct category IDs for each get_posts of course.) the posts_per_page settings gives you more fine-grained control over how many posts from each category you get, but of course you can pass more arguments to get_posts (see the codex page)

...this is an example function called in each display loop:

function custom_post_display($post) {
    $display = '<div class="postitem">';
    $display .= '<h5><a href=".get_permalink($post->ID).">';
    $display .= $post->post_title.'</a></h5>';
    $display .= '<p>'.$post->post_excerpt.'</p>';
    $display .= '</div>';
    return $display;
}

...or displaying anything else you want from the WP_Post (https://codex.wordpress.org/Class_Reference/WP_Post) object...

and now that is all there use the shortcode [custom_news_and_events] on the static page.

you can then style the #frontpagenews and #frontpageevents divs and .postitem class etc

if you don't need the child category subheadings you can remove them and replace the get_post calls to simply:

$news = get_posts(array('category'=>'1,2,3','posts_per_page'=>'10'));
$events = get_posts(array('category'=>'4,5,6','posts_per_page'=>'10'));

which will then get the latest 10 posts from the main and subcategories (as the default for the orderby argument is date.)