Wordpress Timber将自定义分类添加到菜单中


Wordpress Timber add Custom Taxonomy to Menu

在一个基于Timber的Wordpress项目中,我需要在TimberMenu中以程序方式添加自定义分类法(受害者组)的所有术语(带链接),作为菜单点受害者(自定义帖子类型)的子项。

有(优雅的)方法吗?

Wordpress版本:4.4.2木材版本:0.22.5

======更新======

例如:在我的分类术语(受害者群体)中,我有术语a、b、c、d、e

现在我想添加一个名为受害者组的菜单项,其中包含子项a、b、c、d和e

这样我就可以点击a、b、c、d或e中的任何一个,获得一个包含与本学期相关的所有帖子的页面。

客户不允许设置菜单项,所以我必须以编程方式设置它们,并自动向其中添加该分类法的所有新术语(受害者组)。提前欢呼和感谢bambamboole

我通常通过wp_get_nav_menu_items过滤器来做这类事情。当我第一次尝试时,我花了很长时间才了解如何模拟现有的WP_Post或WP_Term作为导航菜单项。你不能只添加项目本身,但你需要对其进行一点调整,以便导航项目仍然链接到正确的目的地。此外,如果你只是添加菜单项,它可能会打乱你的菜单顺序。因此,我们必须用自己的菜单顺序计数器重建菜单数组。

我在几个项目中使用了以下助手函数和wp_get_nav_menu_items过滤器变体的组合,以快速将新项目添加到我的菜单中,无论是自定义帖子类型还是分类。到目前为止效果很好。无论您使用标准的WP Nav Menu Walker还是TimberMenu在主题中显示菜单,这种方法都应该有效。

helper函数

/**
 * Prepare a post or term object to be used as a WP nav menu item.
 *
 * @param string $type                  The type of the object added to the menu. Can be 'page',
 *                                      'category', 'taxonomy' or empty, assuming a custom post type
 * @param WP_Post|WP_Term $menu_post    The object you want to add that is converted
 *                                      to a menu item
 * @param int $menu_parent              The parent menu item you want to add the object to
 * @param int $menu_order_counter       The current menu order counter
 * @param bool $set_new_id              Whether to overwrite the current menu id. You normally want to
 *                                      do this, if you don’t want menu items to disappear randomly.
 * @return void
 */
function pre_setup_nav_menu_item( $type = '', &$menu_post, $menu_parent, $menu_order_counter, $set_new_id = true ) {
    $menu_post->menu_item_parent = $menu_parent;
    $menu_post->menu_order       = $menu_order_counter;
    $menu_post->post_type        = 'nav_menu_item';
    if ( 'page' == $type ) {
        $menu_post->object_id = $menu_post->ID;
        $menu_post->object    = 'page';
        $menu_post->type      = 'post_type';
    } else if ( 'category' == $type ) {
        $menu_post->object_id = $menu_post->term_id;
        $menu_post->object    = 'category';
        $menu_post->type      = 'taxonomy';
    } else if ( 'taxonomy' == $type ) {
        $menu_post->object_id = $menu_post->term_id;
        $menu_post->object    = $menu_post->taxonomy;
        $menu_post->type      = 'taxonomy';
    // Assuming a custom post type
    } else {
        // Use TimberPost if Timber exists
        if ( class_exists( 'Timber' ) ) {
            $menu_post = new TimberPost( $menu_post );
        }
        $menu_post->object_id = $menu_post->ID;
        $menu_post->object    = $type;
        $menu_post->type      = 'post_type';
    }
    /**
     * Create unique ID because in some cases the ID
     * will act as an array key. This way, no menu objects
     * should be overwritten.
     */
    if ( $set_new_id ) {
        $menu_post->ID = uniqid();
    }
}

过滤器

我们将所有现有的菜单项循环显示。当找到菜单项"受害者"时,我们将获得所有受害者组术语,并将其作为子菜单项添加。为了能够找到正确的菜单项,你需要创建一个页面"受害者",然后手动添加到菜单中。在下面的过滤器中,您必须设置页面"受害者"的页面id以及您注册自定义分类法的名称。

/**
 * Filter through nav menu items and add child items and anchor links accordingly
 */
add_filter( 'wp_get_nav_menu_items', function( $items, $menu, $args ) {
    /**
     * The page id of the page that was added manually to the menu
     * and should hold the custom taxonomy menu items.
     */
    $victim_page_id = 22;
    // Name of the custom taxonomy victim groups
    $victim_groups_tax_name = 'victimgroup';
    /**
     * Menus in Admin would also be affected if we wouldn’t
     * check if we’re on the frontend
     */
    if ( ! is_admin() ) {
        // Array to hold the newly built nav menu items array
        $new_items = array();
        // Integer to store custom menu order as we build up the new array
        $menu_order_counter = 1;
        /**
         * Loop through existing menu items and add them to custom menu
         */
        foreach ( $items as $item ) {
            // Add items in normal order
            $item->menu_order = $menu_order_counter;
            $new_items[] = $item;
            $menu_order_counter++;
            // Check for the menu item we want to add our submenu items to
            if ( (int) $item->object_id == $victim_page_id ) {
                // Victim Groups take the current menu item as a parent
                $menu_parent = $item->ID;
                // Get victim groups taxonomy terms
                $terms = Timber::get_terms( $victim_groups_tax_name, array(
                    // You probably want to hide empty taxonomies
                    'hide_empty' => true,
                ) );
                // Loop through terms found and add them as menu items
                foreach ( $terms as $term ) {
                    $term->post_title   = $term->name;
                    $term->post_parent  = $term->parent;
                    pre_setup_nav_menu_item( 'taxonomy', $term, $menu_parent, $menu_order_counter );
                    $term = new TimberTerm( $term );
                    $new_items[] = wp_setup_nav_menu_item( $term );
                    $menu_order_counter++;
                    unset( $term );
                }
            }
        }
        return $new_items;
    }
    return $items;
}, 10, 3);