我的解决方案使用Walker\\u Nav\\u菜单和一个自定义类,主要是从以下帖子中拼凑而成:How do I dynamically populate wp_nav_menu from a custom taxonomy?
解决方案:
//define the custom post type
//could use "page" or "post" as well.
define("MENU_CPT", "action");
//custom function for selecting posts based on a page parent (ne\' term_id)
function hgs_get_children_by_id($parent_id, $post_type=MENU_CPT) {
$args = array(
\'posts_per_page\' => -1,
\'post_type\' => $post_type,
\'post_parent\' => $parent_id,
\'orderby\' => \'menu_order title\',
\'order\' => \'DESC\'
);
return get_posts( $args );
}
//custom nav menu walker class for Take Action Dropdown
class HGS_Walker_Nav_Menu extends Walker_Nav_Menu {
/**
* Display array of elements hierarchically.
*
* It is a generic function which does not assume any existing order of
* elements. max_depth = -1 means flatly display every element. max_depth =
* 0 means display all levels. max_depth > 0 specifies the number of
* display levels.
*
* @since 2.1.0
*
* @param array $elements
* @param int $max_depth
* @return string
*/
function walk( $elements, $max_depth) {
$args = array_slice(func_get_args(), 2);
$output = \'\';
if ($max_depth < -1) //invalid parameter
return $output;
if (empty($elements)) //nothing to walk
return $output;
$id_field = $this->db_fields[\'id\'];
$parent_field = $this->db_fields[\'parent\'];
// flat display
if ( -1 == $max_depth ) {
$empty_array = array();
foreach ( $elements as $e )
$this->display_element( $e, $empty_array, 1, 0, $args, $output );
return $output;
}
/*
* need to display in hierarchical order
* separate elements into two buckets: top level and children elements
* children_elements is two dimensional array, eg.
* children_elements[10][] contains all sub-elements whose parent is 10.
*/
$top_level_elements = array();
$children_elements = array();
foreach ( $elements as $e) {
if ( 0 == $e->$parent_field )
{
//var_dump($e); //for troubleshooting
$top_level_elements[] = $e;
if ( $e->type==\'post_type\' && $e->object == MENU_CPT ) {
$child_posts = hgs_get_children_by_id($e->object_id);
foreach ( $child_posts as $child ) {
$child = wp_setup_nav_menu_item($child);
$child->post_type = \'nav_menu_item\';
$child->menu_item_parent = $e->$id_field;
$child->object = \'custom\';
$child->type = \'custom\';
$child->ID = $e->$id_field.$child->ID;
$children_elements[ $e->$id_field ][] = $child;
$children_elements_classes[] = $child;
}
}
}
else
{
$children_elements[ $e->$parent_field ][] = $e;
}
}
/*
* when none of the elements is top level
* assume the first one must be root of the sub elements
*/
if ( empty($top_level_elements) ) {
$first = array_slice( $elements, 0, 1 );
$root = $first[0];
$top_level_elements = array();
$children_elements = array();
foreach ( $elements as $e) {
if ( $root->$parent_field == $e->$parent_field )
{
$top_level_elements[] = $e;
if ( $e->type==\'post_type\' && $e->object == MENU_CPT ) {
$child_posts = hgs_get_children_by_id($e->object_id);
foreach ( $child_posts as $child ) {
$child = wp_setup_nav_menu_item($child);
$child->post_type = \'nav_menu_item\';
$child->menu_item_parent = $e->$id_field;
$child->object = \'custom\';
$child->type = \'custom\';
$child->ID = $e->$id_field.$child->ID;
$children_elements[ $e->$id_field ][] = $child;
$children_elements_classes[] = $child;
}
}
}
else
{
$children_elements[ $e->$parent_field ][] = $e;
}
}
}
//assing the classes to our dynamically populated posts
if ( $children_elements_classes )
_wp_menu_item_classes_by_context($children_elements_classes);
foreach ( $top_level_elements as $e )
$this->display_element( $e, $children_elements, $max_depth, 0, $args, $output );
/*
* if we are displaying all levels, and remaining children_elements is not empty,
* then we got orphans, which should be displayed regardless
*/
if ( ( $max_depth == 0 ) && count( $children_elements ) > 0 ) {
$empty_array = array();
foreach ( $children_elements as $orphans )
foreach( $orphans as $op )
$this->display_element( $op, $empty_array, 1, 0, $args, $output );
}
return $output;
}
}
我们实现如下菜单:
<?php wp_nav_menu( array(
\'theme_location\' => \'nav-right\',
\'menu\' => \'Right Navigation Column\',
\'container\' => \'div\',
\'container_class\' => \'nav-inner\',
\'container_id\' => \'\',
\'menu_class\' => \'menu\',
\'menu_id\' => \'\',
\'echo\' => true,
\'items_wrap\' => \'<h2>Take Action</h2><ul class="%2$s">%3$s</ul>\',
**\'walker\' => new HGS_Walker_Nav_Menu**
) ); ?>
所以我希望这能帮助别人。如果您在一个菜单中使用各种帖子类型,并且在$e->type和$e->object上运行一个条件,那么它当然是非常可定制的。
如果有人对如何改进这一点有更多的见解或想法,请与我们分享。