WordPress 自定义摘要字数和省略号样式

在 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>很多网站都在网页上放置可以调整字体大小的按钮,这些按钮可以让视力不好的人更轻松的浏览网页。浏览器一般都内置了可 [&hellip;]</p>
    </li>
    <li class="post">
        <h2>WordPress 给置顶文章设置一个到期时间</h2>
        <p>在 WordPress 中,可以使用自带的置顶功能来突出一些文章,让访客优先阅读。但是,文章往往不需要一直是置 [&hellip;]</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 Bing_excerpt_length(){
    return 100;
}
add_filter( 'excerpt_length', 'Bing_excerpt_length' );

通过修改代码中函数的返回值,可以任意设置摘要的字数。然后在循环中使用文章开头提到的方法调用摘要,就会是我们设置的字数。

自定义摘要省略号样式

摘要的结尾一般会有一个省略号,表示此处展示的文章内容只是一部分预览,剩下的内容需要进入到文章页面浏览。

这个省略号默认样式为 [&hellip;],是一个 HTML 转义字符,在网页中实际显示为 […]。可能是为了更加明显吧,给正常的西文省略号添加了一对中括号。

但我觉得,没有中括号反而会更好看一些,所以使用 excerpt_more 钩子修改了摘要省略号的样式

function Bing_excerpt_more(){
    return '&hellip;';
}
add_filter( 'excerpt_more', 'Bing_excerpt_more' );

同样的,可以任意设置函数的返回值,来自定义省略号样式,比如修改成中文的六个点省略号。

另外,也可以在函数里调用一些获取当前文章信息的函数,比如添加文章链接:

function Bing_excerpt_more( $more ){
    if( in_the_loop() ){
        $href_attr = esc_url( get_permalink() );
        $text      = __( '阅读更多', 'Bing' );
        $more      = "<a href='$href_attr'>$text</a>";
    }
    return $more;
}
add_filter( 'excerpt_more', 'Bing_excerpt_more' );

整合函数

上边介绍的方法,无论是修改字数还是省略号,都有一个共同的缺点:它把网站中所有的摘要字数都改了。如果主题里有好几处地点需要使用摘要,并且字数不一致,就会比较麻烦。

而且这种方法也会影响 WordPress 后台的样式。在文章列表的“摘要视图”下,显示的文章摘要同样会被修改字数:

WordPress 自定义摘要字数和省略号样式

所以,这里我使用了一个封装函数,将以上的需求封装到了一起。把下边的函数放到主题的 functions.php 文件或者插件中,即可使用:

/**
 * 获取文章摘要
 *
 * 可以自定义摘要的字数(长度)和省略号样式;
 * 同时,作为 excerpt_length 和 excerpt_more 钩子的回调函数,根据条件返回摘要的字数和省略号样式。
 *
 * @see the_excerpt()
 * @see get_the_excerpt()
 * @see wp_trim_excerpt()
 *
 * @link https://www.endskin.com/excerpt-length-more/
 * 
 * @param int    $length 摘要字数。
 * @param string $more   省略号样式;默认值为西文省略号的 HTML 转义字符(&hellip;)。
 * @param bool   $echo   是否直接输出摘要,分别对应 the_excerpt() 和 get_the_excerpt() 函数;默认值为 True。
 *
 * @return string|int
 */
function Bing_excerpt( $length, $more = '&hellip;', $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() 函数的地方,调用上边创建的Bing_excerpt() 函数即可,参数说明写在函数摘要里。

例如,在文章循环中输出 120 字摘要,省略号为中文六点省略号:

Bing_excerpt( 120, '……' );

或者,获取原始摘要,并保存到变量里:

$excerpt = Bing_excerpt( 100, '&hellip;', false );

文字截取方式

最后,科普一下 WordPress 的文字截取方式。PHP 中截取文字的方法一般有两种,根据数据大小截取和根据字符数量截取

众所周知,东亚语言(例如中文、日文和韩文)在计算机中所占的内存量是一个英文字符的两倍。所以,在截取文本时,如果根据数据大小截取,一般一个中文字符会按两个字符计算;而根据字符数量截取就无论中英文或标点,都是一个字符按一个算。

如果没有特殊优化,按照数据大小截取包含中文的字符时,会比较容易出现文字乱码的情况。

因为截取到最后一个字符时,恰好是个汉字,而中文又需要占两个位置,导致最后一个字被强行扔掉一半,出现乱码。

在 PHP 中,可以使用 “mb_string” 库里的 mb_strimwidth() 函数按照数据大小截取文字,能较好的支持中文,不会出现乱码,但有部分服务器不支持 “mb_string” 库。

WordPress 用的是第二种方法,使用正则表达式将字符串里的所有字符都一个一个分开,再按照需要的字数组合起来。

截取文字的功能被封装在 wp_trim_words() 函数里,我们也可以调用它裁剪其它文字。

 

sss

预见

发表评论

:?::razz::sad::evil::!::smile::oops::grin::eek::shock::???::cool::lol::mad::twisted::roll::wink::idea::arrow::neutral::cry::mrgreen: