4

I want to have a link in the wordpress menu pointing to the latest post of a specific category.

Because I am not able put a dynamic URL in the wordpress menu, my approach was to put a page with a custom page template in the menu.

This page template should behave like the themes single.php but showing that last post from the given category.

Is there a way to include the themes single.php and simulate a request of a specific post?

I tried to copy the content of single.php in a page template and modify the query with

query_posts( array( 'cat' => 9993, 'showposts' => 1) );

If I do that before the_header(), then I will get no posts. If I do it after the_header(), then I get the correct content but the header of the theme will set some specific classes for styling a page. So I need the the_header() function to think the desired post was requested and not the page.

Update: I did not completely use the solution by toscho because I did not get the active menu entry highlighted and in the right position with that. But he pointed me in the right direction with the wp_nav_menu_objects filter.

I had a main-menu item CategoryX which should open directly the latest post from CategoryX, and also opening a sub-menu with links to older posts and other related things. The sub-menu should have also a link to the latest Post (LatestFromX) in it, which should also be highlighted directly after klicking on CategoryX in the main menu.

What I basically did was: Creating dummy menu items with the WP admin backend and then replacing its URL with the filter function.

function wp_menu_add_last_from_category_x( $sorted_menu_items, $args ) {   
    global $wp;

    // get url of latest article in CategoryX (CategoryX has id 9993):
    $latest = get_posts( array( 'numberposts' => 1, 'category' => 9993 ) ); 
    $latest_url = get_permalink($latest[0]->ID);

    // search for the dummy menu items and replace the url:
    foreach ($sorted_menu_items as $key => $item) {
        if ($item->title === 'CategoryX' || $item->title === 'LatestFromX') {
            $sorted_menu_items[$key]->url = $latest_url;
            if ($wp->request == $latest[0]->post_name) {
                $sorted_menu_items[$key]->classes[] = "current-menu-item";
            }
        }
    }

    return $sorted_menu_items;
}

2 Answers 2

5

You can filter wp_nav_menu_objects and add a new item. Here is a simple plugin doing that:

<?php # -*- coding: utf-8 -*-
/**
 * Plugin Name: Latest Post In Menu
 * Description: Append a link to the latest post to all nav menus called with the argument <code>'add_latest_post' => TRUE</code>.
 * Plugin URI:  http://wordpress.stackexchange.com/q/59892/73
 * Version:     2012.07
 * Author:      Thomas Scholz
 * Author URI:  http://toscho.de
 * License:     MIT
 * License URI: http://www.opensource.org/licenses/mit-license.php
 */

add_filter( 'wp_nav_menu_objects', 'wpse_59892_latest_post_in_nav_menu', 10, 2 );

/**
 * Add a link to the latest post to the nav menu.
 *
 * The nav menu has to be called with 'add_latest_post' => TRUE.
 * Example:
 * wp_nav_menu(
 *  array(
 *      'theme_location' => 'primary',
 *      'add_latest_post' => TRUE
 *  )
 * );
 *
 * @wp-hook wp_nav_menu_objects
 * @param   array $sorted_menu_items Existing menu items
 * @param   object $args Nav menu arguments as object.
 * @return  array
 */
function wpse_59892_latest_post_in_nav_menu( $sorted_menu_items, $args )
{
    if ( ! isset ( $args->add_latest_post )                    // argument set?
        or ! $args->add_latest_post                           // argument TRUE?
        or ! $latest = get_posts( array ( 'numberposts' => 1 ) ) // post found?
    )
    {
        return $sorted_menu_items;
    }

    // Uncomment the following line to see what you can change:
    // print '<pre>' . htmlspecialchars( var_export( $sorted_menu_items, TRUE ) ) . '</pre>';

    $post    = $latest[0];
    $content = empty ( $post->post_excerpt ) ? $post->post_content : $post->post_excerpt;
    $link    = array (
        'title'            => $post->post_title,
        'menu_item_parent' => 0,
        'ID'               => '',
        'db_id'            => '',
        'url'              => get_permalink( $post->ID ),
        'classes'          => array (
                0 => '',
                1 => 'menu-item',
                2 => 'menu-item-type-post_type',
                3 => 'menu-item-object-post',
                4 => 'latest-post',
            ),
        // strips all tags and reduces the length to 20 words
        'attr_title'       => wp_trim_words( $content, 20 ),
    );

    $sorted_menu_items[] = (object) $link;

    return $sorted_menu_items;
}

If we write a new post …

enter image description here

… and call the nav menu like this …

wp_nav_menu( 
    array( 
        'theme_location'  => 'primary', 
        'add_latest_post' => TRUE 
    ) 
);

… we get …

enter image description here

The nav menu item has a class latest-post, so we can style it per CSS:

.menu .latest-post a
{
    color: #eee;
    background: #9f0;
}
0

Or use this plugin. No coding of wp_nav_menu required:

https://de.wordpress.org/plugins/dynamic-latest-post-in-nav-menu/

https://github.com/hijiriworld/dynamic-latest-post-in-nav-menu

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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