Wordpress分层自定义帖子类型自动添加到菜单中

时间:2018-01-07 16:18:42

标签: wordpress custom-wordpress-pages

这可能是重复的,但我并没有真正看到我搜索时与我的问题有什么关系。

我在插件中创建了一个分层的自定义帖子类型。我试图自动添加此自定义帖子类型的菜单项,这样当我添加新条目时,它将显示在根据层次结构正确排列的下拉菜单中。我必须选择一个条目,只要它的所有子项都正确填充在菜单中,而不必每次我创建新条目时都必须手动添加它们。

我已经能够在菜单中添加条目了。但它并没有增加孩子。我已经尝试过"自动添加新的顶级条目"选项,但它也没有做任何事情。我找到了一些东西,据说为wp_get_nav_menu_items添加了一个过滤器,但要么我把它放在错误的位置(我在自定义的帖子类型定义类中有它),或者它没用,也没有做我的事情想。

看起来这应该是相对简单的事情 - 看起来所有的功能都会出现,我只是没有找到如何将其链接。

感谢您的帮助。

编辑以在建议的编辑后共享整个文件,以防它有所帮助。

Hint blah.

2 个答案:

答案 0 :(得分:1)

可能还有其他可能的解决方案,但您绝对可以使用wp_get_nav_menu_items过滤器执行此操作。下面是使用此挂钩更改菜单的示例代码。您可以将其插入到插件的主文件中,但更改回调顶部的参数以满足您的需求。

基本上,这会创建一个“虚拟”顶级菜单项,并在此菜单项下插入自定义帖子条目。最终你可以修改它以使用其中一个海关帖子作为顶级项目,并将其余部分列在下面。此外,好处是基于menu_item_parentdb_id属性,它保留了整个层次结构。

/**
 * Blend custom posts into a nav menu
 */
add_filter('wp_get_nav_menu_items', function ($items, $menu, $args) {
    // Change these parameters
    $menuLocation = 'MENU_NAME';// Registered menu location
    $customPostType = 'CUSTOM_POST_TYPE';// Custom post type name
    $newRootMenuName = 'MY_CUSTOM_POSTS';// Name that will appear in the menu

    // Do not show the customized list in the admin pages
    // and customize only the choosen menu
    if (is_admin() || !($menu->slug === $menuLocation)) {
        return $items;
    }

    $rootMenuItemId = PHP_INT_MAX;

    // Adding a new root level menu item
    $items[] = (object)[
        'ID'                => 0,
        'title'             => $newRootMenuName,
        'url'               => '#',
        'menu_item_parent'  => 0,
        'post_parent'       => 0,
        'menu_order'        => count($items) + 1,
        'db_id'             => $rootMenuItemId,

        // These are not necessary for the functionality, but PHP warning will be thrown if not set
        'type'              => 'custom',
        'object'            => 'custom',
        'object_id'         => '',
        'classes'           => [],
    ];

    // Querying custom posts
    $customPosts = get_posts([
        'post_type'        => $customPostType,
        'posts_per_page'   => -1,
    ]);

    // Adding menu item specific properties to `$post` objects
    foreach ($customPosts as $i => $post) {
        $post->title = $post->post_title;
        $post->url = get_permalink($post);
        $post->menu_item_parent = $post->post_parent ? $post->post_parent : $rootMenuItemId;
        $post->menu_order = $i;
        $post->db_id = $post->ID;
    }

    // Merge custom posts into menu items
    $items = array_merge($items, $customPosts);

    return $items;
}, null, 3);

答案 1 :(得分:0)

我接受了dferenc的回答,因为没有他的帮助,我完全不会来这里。但是,根据所有细节和评论,我想显示最终结果,如下所示。 add_filter调用match_locations_filter,按顺序为每个子项调用match_menu_children以创建整个层次结构。要使其工作,您可以将任何自定义帖子类型条目添加到菜单中,它应该自动包含所有子项。

function match_menu_children($parent_menu_ID, $parent_post_id, $ordermin)
    {
        $items = array();

        $childPosts = get_posts([
            'post_type'         => 'match',
            'posts_per_page'    => -1,
            'order_by'          => 'menu_order',
            'order'             => 'ASC',
            'post_parent'       => $parent_post_id,
            ]);
        //print_r($childPosts);

        foreach ($childPosts as $item)
        {       
            $items[] = (object)[
            'ID'                => $item->ID,
            'title'             => $item->post_title,
            'url'               => get_permalink($item),
            'menu_item_parent'  => $parent_menu_ID,
            'post_parent'       => $parentID,
            'menu_order'        => ++$ordermin,
            'db_id'             => $item->ID,
            'type'              => 'custom',
            'object'            => 'custom',
            'object_id'         => '',
            'classes'           => [],
            ];

            $newitems = $this->match_menu_children($item->ID, $item->ID, $ordermin);
            if (count($newitems > 0))
            {
                $ordermin = $ordermin + count($newitems);
                $items = array_merge($items, $newitems) ;       
            }           
        }       
        return $items;
    }

    function match_locations_filter( $items, $menu, $args ) 
    {
        $customPostType = 'match';// Custom post type name      
        $ordermin = count($items) + 1;

        $customPosts = get_posts([
        'post_type'         => $customPostType,
        'posts_per_page'    => -1,
        'order_by'          => 'menu_order',
        'order'             => 'ASC',
        ]);

        foreach ($items as $menuitem)
        {
            foreach ($customPosts as $match)
            {
                if ($menuitem->object_id == $match->ID)
                {   
                    // This menu item IS a match entry.  Populate it with it's children.
                    $newitems = $this->match_menu_children($menuitem->db_id, $match->ID, $ordermin);
                    $ordermin = $ordermin + count($newitems);
                    $items = array_merge($items, $newitems) ;
                }
            }
        }
        return $items;
    }