给菜单menu添加字段并输出自定义的菜单结构

<?php
class Mega_Menu_Walker extends Walker_Nav_Menu {
    // Add properties to track current item and its ancestors
    protected $current_item = null;
    protected $current_item_ancestors = array();

    /**
     * Track the current item before displaying it
     */
    public function display_element($element, &$children_elements, $max_depth, $depth, $args, &$output) {
        // Store current item
        $this->current_item = $element;
        
        // Store ancestors for this item
        $this->current_item_ancestors = array();
        if (isset($element->menu_item_parent) && $element->menu_item_parent > 0) {
            $ancestors = array();
            $ancestor_id = $element->menu_item_parent;
            
            while ($ancestor_id > 0) {
                foreach ($children_elements as $children) {
                    foreach ($children as $child) {
                        if ($child->ID == $ancestor_id) {
                            $ancestors[] = $child;
                            $ancestor_id = $child->menu_item_parent;
                            continue 2;
                        }
                    }
                    $ancestor_id = 0;
                }
            }
            $this->current_item_ancestors = array_reverse($ancestors);
        }
        
        parent::display_element($element, $children_elements, $max_depth, $depth, $args, $output);
    }

    /**
     * Start level based on mega menu type
     */
    public function start_lvl(&$output, $depth = 0, $args = null) {
        $mega_menu_type = '';
        
        // Get mega menu type from parent item
        if (!empty($this->current_item_ancestors)) {
            $parent_item = end($this->current_item_ancestors);
            $mega_menu_type = get_post_meta($parent_item->ID, '_mega_menu_type', true);
        } elseif ($this->current_item) {
            $mega_menu_type = get_post_meta($this->current_item->ID, '_mega_menu_type', true);
        }
        
        if ($depth === 0) {
            switch ($mega_menu_type) {
                case 'product':
                    $output .= '<div class="mega-menu mega-menu-products-container">';
                    break;
                    
                case 'category':
                    $output .= '<div class="mega-menu mega-menu-categories-container">';
                    break;
                    
                case 'post':
                    $output .= '<div class="mega-menu mega-menu-posts-container">';
                    break;
                    
                default:
                    $output .= '<ul class="sub-menu">';
                    break;
            }
        } else {
            // For nested levels
            switch ($mega_menu_type) {
                case 'product':
                    $output .= '<div class="mega-menu-product-submenu">';
                    break;
                    
                case 'category':
                    $output .= '<div class="mega-menu-category-submenu">';
                    break;
                    
                case 'post':
                    $output .= '<div class="mega-menu-post-submenu">';
                    break;
                    
                default:
                    $output .= '<ul class="sub-menu">';
                    break;
            }
        }
    }

    /**
     * End level based on mega menu type
     */
    public function end_lvl(&$output, $depth = 0, $args = null) {
        $mega_menu_type = '';
        
        // Get mega menu type from parent item
        if (!empty($this->current_item_ancestors)) {
            $parent_item = end($this->current_item_ancestors);
            $mega_menu_type = get_post_meta($parent_item->ID, '_mega_menu_type', true);
        } elseif ($this->current_item) {
            $mega_menu_type = get_post_meta($this->current_item->ID, '_mega_menu_type', true);
        }
        
        if ($mega_menu_type && ($mega_menu_type === 'product' || $mega_menu_type === 'category' || $mega_menu_type === 'post')) {
            $output .= '</div>';
        } else {
            $output .= '</ul>';
        }
    }

    /**
     * Start element with proper container
     */
    public function start_el(&$output, $item, $depth = 0, $args = null, $id = 0) {
        $mega_menu_type = get_post_meta($item->ID, '_mega_menu_type', true);
        $parent_mega_type = '';
        
        // Get parent mega menu type
        if ($depth > 0 && !empty($this->current_item_ancestors)) {
            $parent_item = end($this->current_item_ancestors);
            $parent_mega_type = get_post_meta($parent_item->ID, '_mega_menu_type', true);
        }
        
        // Classes
        $classes = empty($item->classes) ? array() : (array) $item->classes;
        
        if ($mega_menu_type && $depth === 0) {
            $classes[] = 'has-mega-menu';
            $classes[] = 'mega-menu-' . $mega_menu_type;
        }
        
        $class_names = join(' ', apply_filters('nav_menu_css_class', array_filter($classes), $item, $args, $depth));
        $class_names = $class_names ? ' class="' . esc_attr($class_names) . '"' : '';
        
        // Determine container element
        $container_element = 'li';
        if ($depth > 0 && $parent_mega_type) {
            switch ($parent_mega_type) {
                case 'product':
                    $container_element = 'div';
                    $class_names = ' class="mega-product-item"';
                    break;
                    
                case 'category':
                    $container_element = 'div';
                    $class_names = ' class="mega-category-item"';
                    break;
                    
                case 'post':
                    $container_element = 'div';
                    $class_names = ' class="mega-post-item"';
                    break;
            }
        }
        
        $output .= '<' . $container_element . $class_names . '>';
        
        // Build menu item
        $atts = array();
        $atts['title']  = !empty($item->attr_title) ? $item->attr_title : '';
        $atts['target'] = !empty($item->target) ? $item->target : '';
        $atts['rel']    = !empty($item->xfn) ? $item->xfn : '';
        $atts['href']   = !empty($item->url) ? $item->url : '';
        
        $attributes = '';
        foreach ($atts as $attr => $value) {
            if (!empty($value)) {
                $attributes .= ' ' . $attr . '="' . esc_attr($value) . '"';
            }
        }
        
        $title = apply_filters('the_title', $item->title, $item->ID);
        
        $item_output = $args->before;
        
        // Generate content based on type
        if ($depth > 0 && $parent_mega_type) {
            switch ($parent_mega_type) {
                case 'product':
                    $item_output .= $this->get_product_item_content($item);
                    break;
                    
                case 'post':
                    $item_output .= $this->get_post_item_content($item);
                    break;
                    
                default:
                    $item_output .= '<a' . $attributes . '>';
                    $item_output .= $args->link_before . $title . $args->link_after;
                    $item_output .= '</a>';
            }
        } else {
            $item_output .= '<a' . $attributes . '>';
            $item_output .= $args->link_before . $title . $args->link_after;
            $item_output .= '</a>';
        }
        
        $item_output .= $args->after;
        
        $output .= apply_filters('walker_nav_menu_start_el', $item_output, $item, $depth, $args);
    }

    /**
     * End element with proper container
     */
    public function end_el(&$output, $item, $depth = 0, $args = null) {
        $parent_mega_type = '';
        if ($depth > 0 && !empty($this->current_item_ancestors)) {
            $parent_item = end($this->current_item_ancestors);
            $parent_mega_type = get_post_meta($parent_item->ID, '_mega_menu_type', true);
        }
        
        $container_element = 'li';
        if ($depth > 0 && in_array($parent_mega_type, ['product', 'category', 'post'])) {
            $container_element = 'div';
        }
        
        $output .= "</{$container_element}>";
    }

    /**
     * Helper method for product content
     */
    private function get_product_item_content($item) {
        $output = '<div class="mega-product-content">';
        if (has_post_thumbnail($item->object_id)) {
            $output .= get_the_post_thumbnail($item->object_id, 'thumbnail');
        }
        $output .= '<h4><a href="' . get_permalink($item->object_id) . '">' . $item->title . '</a></h4>';
        
        if (function_exists('get_woocommerce_price')) {
            $product = wc_get_product($item->object_id);
            if ($product) {
                $output .= '<span class="price">' . $product->get_price_html() . '</span>';
            }
        }
        
        $output .= '</div>';
        return $output;
    }

    /**
     * Helper method for post content
     */
    private function get_post_item_content($item) {
        $output = '<div class="mega-post-content">';
        if (has_post_thumbnail($item->object_id)) {
            $output .= get_the_post_thumbnail($item->object_id, 'thumbnail');
        }
        $output .= '<h4><a href="' . get_permalink($item->object_id) . '">' . $item->title . '</a></h4>';
        $output .= '<p>' . wp_trim_words(get_post_field('post_excerpt', $item->object_id), 10) . '</p>';
        $output .= '</div>';
        return $output;
    }
}

给菜单添加字段

/**
 * Step 1: Add Custom Menu Field
 * Add this to your theme's functions.php
 */
add_action('wp_nav_menu_item_custom_fields', 'add_mega_menu_type_field', 10, 4);
function add_mega_menu_type_field($item_id, $item, $depth, $args) {
    $mega_menu_type = get_post_meta($item_id, '_mega_menu_type', true);
    ?>
    <p class="field-mega-menu-type description description-wide">
        <label for="edit-menu-item-mega-menu-type-<?php echo $item_id; ?>">
            <?php _e('Mega Menu Type'); ?><br />
            <select id="edit-menu-item-mega-menu-type-<?php echo $item_id; ?>"
                    name="menu-item-mega-menu-type[<?php echo $item_id; ?>]">
                <option value="" <?php selected($mega_menu_type, ''); ?>><?php _e('None'); ?></option>
                <option value="product" <?php selected($mega_menu_type, 'product'); ?>><?php _e('Product'); ?></option>
                <option value="category" <?php selected($mega_menu_type, 'category'); ?>><?php _e('Category'); ?></option>
                <option value="post" <?php selected($mega_menu_type, 'post'); ?>><?php _e('Post'); ?></option>
            </select>
        </label>
    </p>
    <?php
}

/**
 * Step 2: Save Custom Menu Field
 */
add_action('wp_update_nav_menu_item', 'save_mega_menu_type_field', 10, 3);
function save_mega_menu_type_field($menu_id, $menu_item_db_id, $menu_item_args) {
    if (isset($_POST['menu-item-mega-menu-type'][$menu_item_db_id])) {
        $mega_menu_type = sanitize_text_field($_POST['menu-item-mega-menu-type'][$menu_item_db_id]);
        update_post_meta($menu_item_db_id, '_mega_menu_type', $mega_menu_type);
    }
}

如果不进入header.php 在functions.php 修改菜单的输出,要用到钩子:

/**
 * Step 4: Register Custom Walker
 * Add this to your theme's functions.php
 */
add_filter('wp_nav_menu_args', 'register_mega_menu_walker');
function register_mega_menu_walker($args) {
    if (!isset($args['theme_location']) || $args['theme_location'] !== 'primary') {
        return $args;
    }
    
    $args['walker'] = new Mega_Menu_Walker();
    return $args;
}
×
给菜单menu添加字段并输出自定义的菜单结构

给菜单menu添加字段并输出自定义的菜单结构

<?php class Mega_...