简体   繁体   中英

Loop posts by category on a menu item from functions PHP Wordpress

First of all 90% of this code is working just need a little push :D

Everything is done inside functions.php

I'm adding an item to my header menu, where it needs to display dynamically some posts inside a specific category.

I'm getting the posts using the function below which was taken and modified for my needs from here

 function get_latest_post_thumbnails_urls() {
    // Set an empty variable which will hold our array of URL's
    $output = [];

    // Set our query args
    $args = [
        'posts_per_page' => 3,
        'fields'         => 'ids', // Only get post ID's
        'meta_query'     => [ // Get posts which has thumbnails only
            [
                'key'     => '_thumbnail_id',
                'compare' => 'EXISTS'
            ]
        ],
        'cat' => '5'
        // Any additional parameters you might need
    ];
    $q = get_posts( $args );

    // ALWAYS make sure we have posts, else return $output
    if ( !$q )
        return $output;

    // Ok, we have posts, lets loop through them and create an array of URL's
    foreach ( $q as $id ) 
        $output[] = wp_get_attachment_url( get_post_thumbnail_id( $id ) );

    // Return our array
    return $output;

}

Then I use the function below to add the menu item ( adapted from here ), but the variable is not displaying in the correct place during the loop. The <li> needs to be inside the <ul> .

add_filter('wp_nav_menu_items', 'add_admin_link', 10, 2);
function add_admin_link($items, $args){

    if( $args->theme_location == 'main_menu' ){
        $items .= '<li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children dropdown menu-item-1441">
        <a class="sf-with-ul" title="Eventos" href="/eventos/"><span class="link-inner">EVENTOS <span class="nav-arrow top-level fa fa-angle-down"></span></span></a>

        <ul class="sub-menu" style="display: none;">'.
        $urls = get_latest_post_thumbnails_urls();
        if ( $urls ) {
                foreach ( $urls as $url ) {
                    // Do something with your thumbnail url
                    echo '<li>'. $url .'</li>';// For testing, remove this
                }
            }
        '</ul>
        </li>';
    }
    return $items;
}

查看循环工作的图像,但在菜单后打印 As you can see in the image, the function is getting all of the correct information, but it is displaying it before the menu item.

//////////////// NEW CODE HELP //////////////////

add_filter('wp_nav_menu_items', 'add_admin_link', 10, 2);
function add_admin_link($items, $args){
    if( $args->theme_location == 'main_menu' ){
        //add your first few elements to the $items variable
        $items .= '<li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children dropdown menu-item-1441">';
        $items .= '<a class="sf-with-ul" title="Eventos" href="/eventos/"><span class="link-inner">EVENTOS <span class="nav-arrow top-level fa fa-angle-down"></span></span></a>';
        $items .= '<ul class="sub-menu" style="display: none;">';


            $args = array(
                'post_type' => 'post',
                'posts_per_page' => -1,
                'cat' => '5'
            );

            $post_query = new WP_Query($args);
        if($post_query->have_posts() ) {
          while($post_query->have_posts() ) {
            $post_query->the_post();

            $items .= '<h2>'. the_title() .'</h2>';

          }
        };


        //close the dom elements
        $items .= '</ul>';
        $items .= '</li>';
    }
    //return the final product

The error you are dealing with is happening because you are echoing your $url variables before you return the menu items.

To resolve this, instead of echoing the urls inside your loop, add them to the $items variable (using .= like you did before) as well and then return the $items like you were already doing.

add_filter('wp_nav_menu_items', 'add_admin_link', 10, 2);
function add_admin_link($items, $args){
    if( $args->theme_location == 'main_menu' ){
        //add your first few elements to the $items variable
        $items .= '<li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children dropdown menu-item-1441">';
        $items .= '<a class="sf-with-ul" title="Eventos" href="/eventos/"><span class="link-inner">EVENTOS <span class="nav-arrow top-level fa fa-angle-down"></span></span></a>';
        $items .= '<ul class="sub-menu" style="display: none;">';
        $urls = get_latest_post_thumbnails_urls();
        if ( $urls ) {
            //loop through your url's
            foreach ( $urls as $url ) {
                //add each url onto the $items variable
                $items .= '<li>'. $url .'</li>';
            }
        }
        //close the dom elements
        $items .= '</ul>';
        $items .= '</li>';
    }
    //return the final product
    return $items;
}

You can also combine both of your functions into a singular function by running your WP_Query inside the menu filter.

Doing it this way will make it easier to add additional post information into your menu items.

Here's an example that adds the featured image, wrapped in a link to the post, with the post title added as a title attribute of the link:

add_filter('wp_nav_menu_items', 'add_admin_link', 10, 2);
function add_admin_link($items, $args){
    if( $args->theme_location == 'main_menu' ){
        //add your first few elements to the $items variable
        $items .= '<li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children dropdown menu-item-1441">';
        $items .= '<a class="sf-with-ul" title="Eventos" href="/eventos/"><span class="link-inner">EVENTOS <span class="nav-arrow top-level fa fa-angle-down"></span></span></a>';
        $items .= '<ul class="sub-menu" style="display: none;">';
        $urls = get_latest_post_thumbnails_urls();

        //build you arguments for the wp query
        $args = array(
            'post_type'     => 'post',
            'posts_per_page'=> -1,
            'tax_query' => array( //only get posts in category 5
                array(
                    'taxonomy' => 'category',
                    'field'    => 'term_id',
                    'terms'    => 5,
                ),
            ),
            'meta_query' => array( //only get posts that have a thumbnail
                array(
                    'key' => '_thumbnail_id',
                    'compare' => 'EXISTS'
                ),
            )
        );

        //create the query and loop through it
        $query = new WP_Query($args);
        if($query->have_posts()) {
            while($query->have_posts()) {
                $query->the_post();
                $thumbnail_id   = get_post_thumbnail_id(); //get the thumbnail id
                $image_src      = wp_get_attachment_image_src($thumbnail_id, 'full')[0]; //you can use either full/large/medium/thumbnail
                $items        .= '<li><a href="'.get_the_permalink().'" title="'.get_the_title().'"><img src="'.$image_src.'"></a></a></li>';
            }
        }
        wp_reset_postdata();

        //close the dom elements
        $items .= '</ul>';
        $items .= '</li>';
    }
    //return the final product
    return $items;
}

Function to loop post fields ID

function get_latest_post_thumbnails_urls()
{
    // Set an empty variable which will hold our array of URL's
    $output = [];

    // Set our query args
    $args = [
        'posts_per_page' => -1,
        'fields'         => 'ids', // Only get post ID's
        'meta_query'     => [ // Get posts which has thumbnails only
            [
                'key'     => '_thumbnail_id',
                'compare' => 'EXISTS'
            ]
        ],
        'cat' => '5'
        // Any additional parameters you might need
    ];
    $q = get_posts( $args );

    // ALWAYS make sure we have posts, else return $output
    if ( !$q )
        return $output;

    // Ok, we have posts, lets loop through them and create an array of URL's
    foreach ( $q as $id ) 
        $output[] = $id;

    // Return our array
    return $output;

}

Function to display my menu item

function add_admin_link($items, $args){
    if( $args->theme_location == 'main_menu' ){
        //add your first few elements to the $items variable
        $items .= '<li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children dropdown menu-item-1441">';
        $items .= '<a class="sf-with-ul" title="Eventos" href="/eventos/"><span class="link-inner">EVENTOS <span class="nav-arrow top-level fa fa-angle-down"></span></span></a>';
        $items .= '<ul class="sub-menu" style="display: none;">';

        $urls = get_latest_post_thumbnails_urls();
        if ( $urls ) {
            //loop through your url's
            foreach ( $urls as $url ) {
                //add each url onto the $items variable
                $items .= '<li><a href="'. get_permalink($url) .'"><span class="link-inner">'. get_the_title($url) .'</span></a></li>';
            }
        }

        //close the dom elements
        $items .= '</ul>';
        $items .= '</li>';
    }
    //return the final product
    return $items;
}

Function to position the menu item in the menu

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

function restructure_menu_links( $reorgitems, $args ) {

    $new_links = array();

    $label = add_admin_link($items, $args);    // add your custom menu item content here

    // Create a nav_menu_item object
    $item = array(
        'title'            => $label,
        'menu_item_parent' => 0,
        'ID'               => 'hidden',
        'db_id'            => '',
        'url'              => $link,
        'classes'          => array( 'menu-item' )
    );

    $new_links[] = (object) $item; // Add the new menu item to our array

    // insert item
    $location = 2;   // insert at 3rd place
    array_splice( $reorgitems, $location, 0, $new_links );

    return $reorgitems;
}

I know this isn't perfect but I thank @Frits for the help I finaly got it working my way _:)

And your wellcome to make it better ;)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM