自定义WordPress的摘要(excerpt)字数和省略号样式
在 WordPress 的主题开发中,我一般推荐使用核心自带的 get_the_excerpt()
函数来获取文章的摘要。如果用户在文章编辑器里手动设置了摘要则调用设置的内容;没手动设置时,也会自动从文章的开头开始,截取一部分内容作为摘要。
在循环中调用文章摘要
想在文章循环中输出当前文章的摘要,可以直接使用 the_excerpt()
函数,例如:
<?php if( have_posts() ): ?>
<ul>
<?php
while( have_posts() ):
the_post();
?>
<li <?php post_class(); ?>>
<?php
the_title( '<h2>', '</h2>' );
the_excerpt();
?>
</li>
<?php endwhile; ?>
</ul>
<?php endif; ?>
上边的代码放到模板文件里,最终会生成类似下方的 HTML 代码:
<ul>
<li class="post">
<h2>WordPress 让访问者调整网页字号</h2>
<p>很多网站都在网页上放置可以调整字体大小的按钮,这些按钮可以让视力不好的人更轻松的浏览网页。浏览器一般都内置了可 […]</p>
</li>
<li class="post">
<h2>WordPress 给置顶文章设置一个到期时间</h2>
<p>在 WordPress 中,可以使用自带的置顶功能来突出一些文章,让访客优先阅读。但是,文章往往不需要一直是置 […]</p>
</li>
<!--省略剩余循环部分-->
</ul>
值得注意的是:调用摘要的两个函数
the_excerpt()
和get_the__excerpt()
的主要区别在于,前者是直接输出,后者是返回,可以保存到变量里。并且,
the_excerpt()
函数会自动给摘要添加<p>
标签,而get_the_excerpt()
不会。可以理解为,the_excerpt()
输出的是一段经过处理的 HTML 代码,给摘要进行了自动换行、解析表情符号为图片和转义引号等操作;而get_the_excerpt()
是原始的文本摘要,除了文字截取,没有经过任何处理。
自定义摘要字数
这时候问题来了,用户没设置摘要时,应该从文章中截取多少字用做摘要呢?答案是 55 个字,因为 WordPress 默认就是这样设计的,但我们可以修改它。
在制作主题时,摘要需要多少字往往取决于页面的样式允许它有多大的空间,而不是天生设定好的 55 字。
这时,就可以使用 excerpt_length
过滤器来自定义文章摘要的字数(长度)。比如,在主题的 functions.php 中添加以下代码,就可以将所有的摘要字数都规定为 100 字:
function tiezhu_excerpt_length(){
return 100;
}
add_filter( 'excerpt_length', 'tiezhu_excerpt_length' );
通过修改代码中函数的返回值,可以任意设置摘要的字数。然后在循环中使用文章开头提到的方法调用摘要,就会是我们设置的字数。
自定义摘要省略号样式
摘要的结尾一般会有一个省略号,表示此处展示的文章内容只是一部分预览,剩下的内容需要进入到文章页面浏览。
这个省略号默认样式为 […]
,是一个 HTML 转义字符,在网页中实际显示为 […]
。可能是为了更加明显吧,给正常的西文省略号添加了一对中括号。
但我觉得,没有中括号反而会更好看一些,所以使用 excerpt_more
钩子修改了摘要省略号的样式:
function tiezhu_excerpt_more(){
return '…';
}
add_filter( 'excerpt_more', 'tiezhu_excerpt_more' );
同样的,可以任意设置函数的返回值,来自定义省略号样式,比如修改成中文的六个点省略号。
另外,也可以在函数里调用一些获取当前文章信息的函数,比如添加文章链接:
function tiezhu_excerpt_more( $more ){
if( in_the_loop() ){
$href_attr = esc_url( get_permalink() );
$text = __( '阅读更多', 'read more' );
$more = "<a href='$href_attr'>$text</a>";
}
return $more;
}
add_filter( 'excerpt_more', 'tiezhu_excerpt_more' );
整合函数
上边介绍的方法,无论是修改字数还是省略号,都有一个共同的缺点:它把网站中所有的摘要字数都改了。如果主题里有好几处地点需要使用摘要,并且字数不一致,就会比较麻烦。
而且这种方法也会影响 WordPress 后台的样式。在文章列表的“摘要视图”下,显示的文章摘要同样会被修改字数:
/**
* 获取文章摘要
*
* 可以自定义摘要的字数(长度)和省略号样式;
* 同时,作为 excerpt_length 和 excerpt_more 钩子的回调函数,根据条件返回摘要的字数和省略号样式。
*
* @see the_excerpt()
* @see get_the_excerpt()
* @see wp_trim_excerpt()
*
* @link https://www.wpzxbj.com/kaifa/1.html
*
* @param int $length 摘要字数。
* @param string $more 省略号样式;默认值为西文省略号的 HTML 转义字符(…)。
* @param bool $echo 是否直接输出摘要,分别对应 the_excerpt() 和 get_the_excerpt() 函数;默认值为 True。
*
* @return string|int
*/
function tiezhu_excerpt( $length, $more = '…', $echo = true ){
static $excerpt_length, $excerpt_more;
$current_filter = current_filter();
if( $current_filter == 'excerpt_length' ) return $excerpt_length;
if( $current_filter == 'excerpt_more' ) return $excerpt_more;
$excerpt_length = $length;
$excerpt_more = $more;
$callable = __FUNCTION__;
add_filter( 'excerpt_length', $callable, 18 );
add_filter( 'excerpt_more', $callable, 18 );
$excerpt = $echo ? the_excerpt() : get_the_excerpt();
remove_filter( 'excerpt_length', $callable, 18 );
remove_filter( 'excerpt_more', $callable, 18 );
unset( $excerpt_length, $excerpt_more );
return $excerpt;
}
使用方法很简单,在原来需要使用 the_excerpt()
或者 get_the_excerpt()
函数的地方,调用上边创建的 tiezhu_excerpt()
函数即可,参数说明写在函数摘要里。
例如,在文章循环中输出 120 字摘要,省略号为中文六点省略号:
tiezhu_excerpt( 120, '……' );
或者,获取原始摘要,并保存到变量里:
$excerpt = tiezhu_excerpt( 100, '…', false );
文字截取方式
最后,科普一下 WordPress 的文字截取方式。PHP 中截取文字的方法一般有两种,根据数据大小截取和根据字符数量截取。
众所周知,东亚语言(例如中文、日文和韩文)在计算机中所占的内存量是一个英文字符的两倍。所以,在截取文本时,如果根据数据大小截取,一般一个中文字符会按两个字符计算;而根据字符数量截取就无论中英文或标点,都是一个字符按一个算。
如果没有特殊优化,按照数据大小截取包含中文的字符时,会比较容易出现文字乱码的情况。
因为截取到最后一个字符时,恰好是个汉字,而中文又需要占两个位置,导致最后一个字被强行扔掉一半,出现乱码。
在 PHP 中,可以使用 “mb_string” 库里的
mb_strimwidth()
函数按照数据大小截取文字,能较好的支持中文,不会出现乱码,但有部分服务器不支持 “mb_string” 库。
WordPress 用的是第二种方法,使用正则表达式将字符串里的所有字符都一个一个分开,再按照需要的字数组合起来。
截取文字的功能被封装在 wp_trim_words()
函数里,我们也可以调用它裁剪其它文字。