在 WordPress 3.0 中,你将会在管理控制面板的 Appearance(外观) 菜单下见到一个被称为 Menus 的菜单系统。下图展示了该页面的 4 个主要元素。每个菜单条目都有它自己的配置选项。添加了条目之后,你就可以打开它,对其属性(这些属性在 WordPress 3.1 中进行了调整,请参考后面的留言)进行编辑。那么要将某个特定的菜单添加到主题中的某个位置,需要将该菜单登记进去。否则,我们就不知道哪个菜单应该在哪个位置上出现。该函数有两种使用方式(注意有一个 s 的区别):
- register_nav_menu(): 注册一个单一的菜单位置。
- register_nav_menus(): 注册多个菜单位置。
在下面的例子中,我们将在主题的 functions.php 函数中注册一个称为 Primary Menu 的菜单
- add_action( 'init', 'register_my_menu' );
- function register_my_menu() {
- register_nav_menu( 'primary-menu', __( 'Primary Menu' ) );
- }
其中 “primary-menu” 是我们在代码中用于标识该菜单的别名。“Primary Menu” 是我们在控制面板中用于标识该菜单的标签。当然,我们也可以利用类似的方式注册多个菜单。
- add_action( 'init', 'register_my_menus' );
- function register_my_menus() {
- register_nav_menus(
- array(
- 'primary-menu' => __( 'Primary Menu' ),
- 'secondary-menu' => __( 'Secondary Menu' ),
- 'tertiary-menu' => __( 'Tertiary Menu' )
- )
- );
- }
大多数主题都会在 header.php 模板中调用一个导航栏,但是 MENUS 能够放在主题的任何位置。调用自定义导航菜单的最简单形式为:
- <?php wp_nav_menu(); ?>
该语句将会加载用户创建的菜单或者如果导航菜单不存在的话就调用一个标准的页面列表。我们可能想对这个调用进行更多的控制。如果从前面提到的 Primary Menu 来调用一个导航菜单,可以这么做:
- <?php
- wp_nav_menu( array(
- 'theme_location' => '',//导航别名
- 'menu' => '', //期望显示的菜单
- 'container' => 'div', //容器标签
- 'container_class' => '',//ul父节点class值
- 'container_id' => '', //ul父节点id值
- 'menu_class' => 'menu', //ul节点class值
- 'menu_id' => '', //ul节点id值
- 'echo' => true,//是否输出菜单,默认为真
- 'fallback_cb' => 'wp_page_menu', //菜单不存在时,返回默认菜单,设为false则不返回
- 'before' => '', //链接前文本
- 'after' => '', //链接后文本
- 'link_before' => '', //链接文本前
- 'link_after' => '',//链接文本后
- 'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>', //如何包装列表
- 'depth' => 0, //菜单深度,默认0
- 'walker' => '' //自定义walker
- ) );
- ?>
当然,不止是文本,也可以输出 HTML 标签,所以灵活使用这四个参数,可以打造出别具一格的导航菜单。但是这种菜单的输出都是 WordPress 格式化的,有些时候我们开发主题的时候需要完全自定义菜单的输出那么就需要用到一下方法,比如我需要生成的 html:
- <ul class="main-nav">
- <li class="item">
- <a href="http://example.com/?p=123" class="title">Title</a>
- <a href="http://example.com/?p=123" class="desc">Description</a>
- <ul class="sub-menu">
- <li class="item">
- <a href="http://example.com/?p=123" class="title">Title</a>
- <a href="http://example.com/?p=123" class="desc">Description</a>
- </li>
- </ul>
- </li>
- <li class="item">
- <a href="http://example.com/?p=123" class="title">Title</a>
- <a href="http://example.com/?p=123" class="desc">Description</a>
- </li>
- </ul>
我目前使用 wp_get_nav_menu_items 从我的菜单中获取所有的项目作为数组。现在我可以使用下面的代码生成上面的 html 没有子菜单:
- <?php
- $menu_name = 'main-nav';
- $locations = get_nav_menu_locations()
- $menu = wp_get_nav_menu_object( $locations[ $menu_name ] );
- $menuitems = wp_get_nav_menu_items( $menu->term_id, array( 'order' => 'DESC' ) );
- foreach ( $menuitems as $item ):
- $id = get_post_meta( $item->ID, '_menu_item_object_id', true );
- $page = get_page( $id );
- $link = get_page_link( $id ); ?>
- <li class="item">
- <a href="<?php echo $link; ?>" class="title">
- <?php echo $page->post_title; ?>
- </a>
- <a href="<?php echo $link; ?>" class="desc">
- <?php echo $page->post_excerpt; ?>
- </a>
- </li>
- <?php endforeach; ?>
- //如果有子菜单,向下钻取,如果我们到达子菜单和菜单的末尾,关闭。完整代码解释,首先将菜单项作为一个平面数组:
- <?php
- $menu_name = 'main_nav';
- $locations = get_nav_menu_locations();
- $menu = wp_get_nav_menu_object( $locations[ $menu_name ] );
- $menuitems = wp_get_nav_menu_items( $menu->term_id, array( 'order' => 'DESC' ) );
- ?>
- //然后在菜单项的数组上进行迭代:
- <nav>
- <ul class="main-nav">
- <?php
- $count = 0;
- $submenu = false;
- foreach( $menuitems as $item ):
- // set up title and url
- $title = $item->title;
- $link = $item->url;
- // item does not have a parent so menu_item_parent equals 0 (false)
- if ( !$item->menu_item_parent ):
- // save this id for later comparison with sub-menu items
- $parent_id = $item->ID;
- ?>
- //撰写第一个父项目li:
- <li class="item">
- <a href="<?php echo $link; ?>" class="title">
- <?php echo $title; ?>
- </a>
- <?php endif; ?>
- //检查此项目的父ID是否与存储的父ID匹配:
- <?php if ( $parent_id == $item->menu_item_parent ): ?>
- //开始子菜单< ul>并将$ submenu标志设置为true以供稍后参考:
- <?php if ( !$submenu ): $submenu = true; ?>
- <ul class="sub-menu">
- <?php endif; ?>
- //编写子菜单项:
- <li class="item"><a href="<?php echo $link; ?>" class="title"><?php echo $title; ?></a></li>
- //如果下一个项目不具有相同的父ID,并且已经声明了子菜单,则关闭子菜单ul
- <?php if ( $menuitems[ $count + 1 ]->menu_item_parent != $parent_id && $submenu ): ?>
- </ul>
- <?php $submenu = false; endif; ?>
- <?php endif; ?>
- //再次,如果数组中的下一个项目不具有相同的父标识关闭li
- <?php if ( $menuitems[ $count + 1 ]->menu_item_parent != $parent_id ): ?>
- </li>
- <?php $submenu = false; endif; ?>
- <?php $count++; endforeach; ?>
- </ul>
- </nav>