WordPress 的文章导航

文章导航是什么? 一个外国朋友告诉我, 他们管它叫 Breadcrumb trail 或者 Breadcrumb navigation, 翻译过来就是文章导航或者文章路径, 对吧? 具体叫什么我真不确定, 或者看看下面的截图你就会知道我在说什么了.

WordPress 的面包屑

这个友好的导航功能, 我最先是在论坛上看到的, 形式一般如下:
首页 > 模块 > 文章

有了它, 访客就可以方便地访问同类的文章, 并明确文章的所属, 对提高用户体验和网站的 PV 值都很有帮助. 我在制作 iNove 主题的时候也加上了这个功能, 但是只能处理子分类, 形式如下:
首页 > 分类 > 文章

最近我在制作一个主题, 客户要求能实现多层次的文章导航, 形式如下:
首页 > 分类 > 子分类 > 第二层子分类 > ... > 第 N 层子分类 > 文章

一般我们会在 the_post() 后面调用 the_category() 生成分类内容. 为此我翻了一下 WordPress 的源代码, 发现 the_category() 方法可能会用到 category-template.php 文件里的另两个方法. 下面我将以注释的形式讲解一下这两个方法, 如发现误解之处, 请指正.

获取父级分类 get_category_parents

/**
 * 获取父级分类 (包含分隔符).
 *
 * @since 1.2.0
 *
 * @param int $id 分类 ID.
 * @param bool $link 默认为 false, 为真时返回的分类包含链接.
 * @param string $separator 分类间分隔符, 默认是 '/'.
 * @param bool $nicename 默认为 false, 为真时返回分类显示为分类别名, 否则显示分类名.
 * @param array $visited 防止分类重复显示 (调用该方法时请不用理会这个参数, 本人认为这只是为了顺利完成迭代处理).
 * @return string
 */
function get_category_parents( $id, $link = false, $separator = '/', $nicename = false, $visited = array() ) {
	// 准备返回的 HTML 字符串
	$chain = '';
 
	// 通过 ID 获取分类
	$parent = &get_category( $id );
 
	// 如果该分类已经定义过, 立即返回
	if ( is_wp_error( $parent ) )
		return $parent;
 
	// 以分类别名或者分类名作为分类链接的显示文本
	if ( $nicename )
		$name = $parent->slug;
	else
		$name = $parent->cat_name;
 
	// 如果该分类还有父分类, 分类不是连向自己, 并且还没有处理过
	if ( $parent->parent && ( $parent->parent != $parent->term_id ) && !in_array( $parent->parent, $visited ) ) {
		// 把当前分类的父分类添加到已处理的数组中, 避免以后被重复处理
		$visited[] = $parent->parent;
		// 迭代处理父分类
		$chain .= get_category_parents( $parent->parent, $link, $separator, $nicename, $visited );
	}
 
	// 以链接或者文本形式 (包含分隔符) 将分类拼接到准备返回的 HTML 字符串中
	if ( $link )
		$chain .= '<a href="' . get_category_link( $parent->term_id ) . '" title="' . sprintf( __( "View all posts in %s" ), $parent->cat_name ) . '">'.$name.'</a>' . $separator;
	else
		$chain .= $name.$separator;
 
	// 返回 HTML 字符串 (结果)
	return $chain;
}

获取父级分类 get_the_category_list

/**
 * 获取分类列表, 并以 HTML 列表方式或者自定义格式返回.
 *
 * @since 1.5.1
 *
 * @param string $separator 默认为空, 显示在各分类之间的分隔符.
 * @param string $parents 指示如何显示父级的分类.
 * @param int $post_id 获取某一文章 ID 对应的分类.
 * @return string
 */
function get_the_category_list( $separator = '', $parents='', $post_id = false ) {
	global $wp_rewrite;
 
	// 找到当前文章对应的分类 (数组, 因为文章可以属于多个分类)
	$categories = get_the_category( $post_id );
 
	// 如果分类数组为空, 在 the_category 方法中当作 '未分类' 进行处理
	if ( empty( $categories ) )
		return apply_filters( 'the_category', __( 'Uncategorized' ), $separator, $parents );
 
	$rel = ( is_object( $wp_rewrite ) && $wp_rewrite->using_permalinks() ) ? 'rel="category tag"' : 'rel="category"';
 
	// 准备返回的 HTML 字符串
	$thelist = '';
 
	// 如果分隔符为空, 返回分类的 HTML 列表
	if ( '' == $separator ) {
		// 列表的开头, 是一个 unordered list
		$thelist .= '<ul class="post-categories">';
 
		// 循环处理所有分类
		foreach ( $categories as $category ) {
			// 每个分类项的开头
			$thelist .= "\n\t<li>";
			switch ( strtolower( $parents ) ) {
 
				// 如果以 'multiple' 模式显示父分类, 每层的分类会独立成一个链接
				case 'multiple':
					// 父分类存在的话, 获取父分类的 HTML 代码并拼接到准备输出的 HTML 字符串中
					if ( $category->parent )
						$thelist .= get_category_parents( $category->parent, true, $separator );
					// 最后把当前分类的 HTML 代码和分类也拼接到准备输出的 HTML 字符串中
					$thelist .= '<a href="' . get_category_link( $category->term_id ) . '" title="' . sprintf( __( "View all posts in %s" ), $category->name ) . '" ' . $rel . '>' . $category->name.'</a></li>';
					break;
 
				// 如果以 'single' 模式显示父分类, 所有分类作为一个链接
				case 'single':
					// 链接的开头
					$thelist .= '<a href="' . get_category_link( $category->term_id ) . '" title="' . sprintf( __( "View all posts in %s" ), $category->name ) . '" ' . $rel . '>';
					// 父分类存在的话, 获取父分类的 HTML 代码并拼接到准备输出的 HTML 字符串中
					if ( $category->parent )
						$thelist .= get_category_parents( $category->parent, false, $separator );
					// 当然分类的名字和链接的结尾
					$thelist .= $category->name.'</a></li>';
					break;
 
				// 如果以默认模式显示父分类, 即不显示父分类
				case '':
				default:
					$thelist .= '<a href="' . get_category_link( $category->term_id ) . '" title="' . sprintf( __( "View all posts in %s" ), $category->name ) . '" ' . $rel . '>' . $category->cat_name.'</a></li>';
			}
		}
 
		// 列表的结尾
		$thelist .= '</ul>';
 
	// 如果分隔符不为空, 返回一段格式化的 HTML
	} else {
		// 计数器
		$i = 0;
 
		// 循环处理所有分类
		foreach ( $categories as $category ) {
			// 第一个分类的前面不显示分隔符
			if ( 0 < $i )
				$thelist .= $separator . ' ';
			switch ( strtolower( $parents ) ) {
 
				// 如果以 'multiple' 模式显示父分类, 每层的分类会独立成一个链接
				case 'multiple':
					if ( $category->parent )
						$thelist .= get_category_parents( $category->parent, true, $separator );
					$thelist .= '<a href="' . get_category_link( $category->term_id ) . '" title="' . sprintf( __( "View all posts in %s" ), $category->name ) . '" ' . $rel . '>' . $category->cat_name.'</a>';
					break;
 
				// 如果以 'single' 模式显示父分类, 所有分类作为一个链接
				case 'single':
					$thelist .= '<a href="' . get_category_link( $category->term_id ) . '" title="' . sprintf( __( "View all posts in %s" ), $category->name ) . '" ' . $rel . '>';
					if ( $category->parent )
						$thelist .= get_category_parents( $category->parent, false, $separator );
					$thelist .= "$category->cat_name</a>";
					break;
				case '':
 
				// 如果以默认模式显示父分类, 即不显示父分类
				default:
					$thelist .= '<a href="' . get_category_link( $category->term_id ) . '" title="' . sprintf( __( "View all posts in %s" ), $category->name ) . '" ' . $rel . '>' . $category->name.'</a>';
			}
 
			// 计数器自增
			++$i;
		}
	}
 
	return apply_filters( 'the_category', $thelist, $separator, $parents );
}

在主题中加入文章导航

1. 不包含父级分类的文章导航
这里用到 the_category() 方法的默认模式, 会调用 get_the_category_list() 生成最后一层的子分类 (分类可能不只一个) 组成的 HTML 字符串并打印到页面上. 代码如下:

<a title="Go to homepage" href="<?php echo get_settings('home'); ?>/">Home</a> <!-- 首页链接 -->
 &gt; <?php the_category(', '); ?> <!-- 每个分类以逗号分隔 -->
 &gt; <?php the_title(); ?> <!-- 文章链接 -->

2. 包含父级分类的文章导航
我们要用的是 the_category() 方法的 multiple 模式, 而他会调用 get_the_category_list()get_category_parents() 两个方法生成一个包含所有父分类的 HTML 字符串并打印到页面上. 代码如下:

<a title="Go to homepage" href="<?php echo get_settings('home'); ?>/">Home</a> <!-- 首页链接 -->
 &gt; <?php the_category(' &gt; ', 'multiple'); ?> <!-- 每个分类以 > 分隔, 父级分类在前, 子分类在后 -->
 &gt; <?php the_title(); ?> <!-- 文章链接 -->

当然, 只要你愿意, 可以将这段代码取代 iNove 主题里 single.php 文件的 id="postpath" 部分, 我并不准备在以后版本的 iNove 主题中使用这个多级的文章导航.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值