阐述 WordPress `the_excerpt()` 函数的源码:如何生成文章摘要并应用 `the_excerpt` 过滤器。

早上好,各位代码爱好者!今天,咱们来聊聊 WordPress 里一个低调但实用的小家伙——the_excerpt() 函数。别看它名字简单,背后可藏着不少故事。今天,咱们就扒开它的源码,看看它到底是怎么生成文章摘要,并且巧妙地运用 the_excerpt 过滤器。

1. 什么是 the_excerpt()?它有什么用?

首先,咱们得明白 the_excerpt() 的作用。简单来说,它用于在 WordPress 主题中显示文章的摘要。 摘要可以手动编写,也可以自动生成。

  • 手动摘要: 在文章编辑器的“摘要” (Excerpt) 栏里填写的内容。
  • 自动摘要: 如果没有手动填写摘要,WordPress 会截取文章内容的前面一部分作为摘要。

the_excerpt() 主要用在文章列表页、搜索结果页、归档页等地方,让用户快速了解文章的内容,决定是否要点击阅读全文。

2. the_excerpt() 的源码剖析

让我们直接深入 WordPress 的源码,找到 the_excerpt() 函数的真身。它通常位于 wp-includes/template.php 文件中。 精简后的代码如下(为了便于理解,略去了一些兼容性处理和边缘情况):

function the_excerpt() {
    /**
     * Filters the excerpt.
     *
     * @since 2.5.0
     *
     * @param string $excerpt The excerpt text.
     */
    $excerpt = apply_filters( 'get_the_excerpt', get_the_excerpt() );

    echo apply_filters( 'the_excerpt', $excerpt );
}

是不是很简单? 别急,精彩的还在后面。

  • get_the_excerpt() 这个函数才是真正干活的。它负责获取文章的摘要。
  • apply_filters( 'get_the_excerpt', ... ) 这是一个过滤器。允许开发者修改 get_the_excerpt() 函数的返回值。
  • echo apply_filters( 'the_excerpt', ... ) 这又是一个过滤器。允许开发者修改最终输出的摘要内容。然后,echo 将结果输出到页面上。

3. get_the_excerpt():摘要的获取与生成

get_the_excerpt() 函数才是核心。它决定了摘要的内容。源码如下 (同样进行了精简):

function get_the_excerpt( $post = null ) {
    $post = get_post( $post );

    if ( empty( $post ) ) {
        return '';
    }

    if ( post_password_required( $post ) ) {
        return __( 'There is no excerpt because this is a protected post.' );
    }

    $excerpt = $post->post_excerpt;

    if ( empty( $excerpt ) ) {
        $excerpt = get_the_content( __( 'Continue reading <span class="screen-reader-text">%s</span>', 'textdomain' ) . ' &rarr;', false, $post );
        $excerpt = strip_shortcodes( $excerpt );

        $excerpt = apply_filters( 'the_content', $excerpt );
        $excerpt = str_replace( ']]>', ']]&gt;', $excerpt );
        $excerpt = strip_tags( $excerpt, '<p><br><img><a>' );
        $excerpt_length = apply_filters( 'excerpt_length', 55 );
        $excerpt_more   = apply_filters( 'excerpt_more', ' &hellip;' );

        $excerpt = wp_trim_words( $excerpt, $excerpt_length, $excerpt_more );
    }

    return apply_filters( 'get_the_excerpt', $excerpt );
}

我们来一步一步地解读这段代码:

  1. 获取文章对象: get_post( $post ) 获取文章对象。如果没有传入 $post,则获取当前文章。

  2. 密码保护判断: post_password_required( $post ) 判断文章是否设置了密码保护。如果是,则返回一个提示信息。

  3. 获取手动摘要: $excerpt = $post->post_excerpt; 尝试获取文章的 post_excerpt 字段,也就是手动填写的摘要。

  4. 自动生成摘要(如果手动摘要为空): 如果 $excerpt 为空,说明没有手动填写摘要,那么就需要自动生成摘要了。

    • 获取文章内容: $excerpt = get_the_content( __( 'Continue reading <span class="screen-reader-text">%s</span>', 'textdomain' ) . ' &rarr;', false, $post ); 获取文章的全部内容。 get_the_content 函数会应用 the_content 过滤器,所以这里获取的内容可能已经被插件或主题修改过了。

    • 移除简码: $excerpt = strip_shortcodes( $excerpt ); 移除文章内容中的简码 (Shortcodes)。简码是 WordPress 中一种方便的标记语言,用于在文章中插入复杂的内容,例如视频、图库等。但是,在摘要中通常不需要显示这些简码,所以需要移除。

    • 再次应用the_content过滤器: $excerpt = apply_filters( 'the_content', $excerpt ); 再次应用 the_content 过滤器。这样做可能是为了确保在提取摘要之前,内容已经经过了必要的处理。

    • 替换特殊字符: $excerpt = str_replace( ']]>', ']]&gt;', $excerpt ); 替换特殊字符 ]]>,避免在某些情况下出现问题。

    • 移除 HTML 标签: $excerpt = strip_tags( $excerpt, '<p><br><img><a>' ); 移除 HTML 标签,只保留 <p><br><img><a> 标签。 保留这些标签是为了让摘要的格式更清晰,例如保留段落、换行、图片和链接。

    • 设置摘要长度和省略号:

      $excerpt_length = apply_filters( 'excerpt_length', 55 );
      $excerpt_more   = apply_filters( 'excerpt_more', ' &hellip;' );
      
      $excerpt = wp_trim_words( $excerpt, $excerpt_length, $excerpt_more );
      • $excerpt_length = apply_filters( 'excerpt_length', 55 ); 通过 excerpt_length 过滤器获取摘要的长度。默认情况下,摘要的长度为 55 个单词。
      • $excerpt_more = apply_filters( 'excerpt_more', ' &hellip;' ); 通过 excerpt_more 过滤器获取省略号。默认情况下,省略号为 &hellip; (也就是 ... 的 HTML 实体)。
      • wp_trim_words( $excerpt, $excerpt_length, $excerpt_more ); 使用 wp_trim_words() 函数截取摘要的长度,并在末尾添加省略号。
  5. 返回摘要: return apply_filters( 'get_the_excerpt', $excerpt ); 返回最终的摘要,并应用 get_the_excerpt 过滤器。

4. 过滤器的妙用:get_the_excerptthe_excerpt

现在,我们来重点说说 get_the_excerptthe_excerpt 这两个过滤器。它们允许开发者在不修改 WordPress 核心代码的情况下,自定义摘要的生成和显示方式。

  • get_the_excerpt 过滤器: 这个过滤器在 get_the_excerpt() 函数的末尾被调用,允许开发者修改摘要的内容。例如,可以修改摘要的长度、添加自定义的 HTML 标签、或者根据文章的分类添加不同的摘要内容。
  • the_excerpt 过滤器: 这个过滤器在 the_excerpt() 函数的末尾被调用,允许开发者修改最终输出的摘要内容。例如,可以修改摘要的样式、添加自定义的 CSS 类、或者在摘要前后添加一些额外的内容。

举例说明:如何使用过滤器修改摘要的长度和省略号

假设我们想要将摘要的长度修改为 30 个单词,并将省略号修改为 [阅读更多]。我们可以使用以下代码:

add_filter( 'excerpt_length', 'my_excerpt_length' );
function my_excerpt_length( $length ) {
    return 30;
}

add_filter( 'excerpt_more', 'my_excerpt_more' );
function my_excerpt_more( $more ) {
    return ' [阅读更多]';
}

这段代码会将摘要的长度修改为 30 个单词,并将省略号修改为 [阅读更多]。是不是很简单?

5. wp_trim_words() 函数:精准的单词截取

wp_trim_words() 函数是 WordPress 中用于截取字符串的函数。它可以根据单词的数量截取字符串,并添加省略号。它的源码如下 (精简版):

function wp_trim_words( $text, $num_words = 55, $more = null ) {
    if ( null === $more ) {
        $more = __( '&hellip;' );
    }

    $original_text = $text;
    $text = wp_strip_all_tags( $text );

    $words_array = preg_split( "/[nrt ]+/", $text, $num_words + 1, PREG_SPLIT_NO_EMPTY );
    $words_array = array_slice( $words_array, 0, $num_words );

    $sep = ' ';
    $text = implode( $sep, $words_array );

    if ( strip_tags( $text ) == strip_tags( $original_text ) ) {
        return $text;
    }

    return rtrim( $text ) . $more;
}

这段代码的逻辑如下:

  1. 移除 HTML 标签: wp_strip_all_tags( $text ) 移除字符串中的所有 HTML 标签。

  2. 分割成单词数组: preg_split( "/[nrt ]+/", $text, $num_words + 1, PREG_SPLIT_NO_EMPTY ) 使用正则表达式将字符串分割成单词数组。

  3. 截取单词数组: array_slice( $words_array, 0, $num_words ) 截取单词数组的前 $num_words 个单词。

  4. 连接成字符串: implode( $sep, $words_array ) 使用空格将单词数组连接成字符串。

  5. 添加省略号: rtrim( $text ) . $more 在字符串的末尾添加省略号。

6. 总结:the_excerpt() 的工作流程

现在,我们来总结一下 the_excerpt() 函数的工作流程:

  1. 获取文章对象。
  2. 判断文章是否设置了密码保护。
  3. 尝试获取手动摘要。
  4. 如果手动摘要为空,则自动生成摘要:
    • 获取文章内容。
    • 移除简码。
    • 移除 HTML 标签。
    • 截取摘要的长度,并添加省略号。
  5. 应用 get_the_excerpt 过滤器。
  6. 输出摘要,并应用 the_excerpt 过滤器。

7. 实际应用:修改摘要的 HTML 结构

假设我们想让摘要包裹在一个自定义的 <div> 标签中,并添加一个自定义的 CSS 类。我们可以使用 the_excerpt 过滤器来实现:

add_filter( 'the_excerpt', 'my_excerpt_wrapper' );
function my_excerpt_wrapper( $excerpt ) {
    return '<div class="my-custom-excerpt">' . $excerpt . '</div>';
}

这段代码会将摘要包裹在一个 class="my-custom-excerpt"<div> 标签中。

8. 表格总结:关键函数和过滤器

为了方便大家理解,我们用一个表格来总结一下 the_excerpt() 函数中涉及的关键函数和过滤器:

函数/过滤器 作用
the_excerpt() 用于在主题中显示文章的摘要。
get_the_excerpt() 用于获取文章的摘要。
apply_filters() WordPress 的过滤器函数,允许开发者修改函数或变量的值。
get_the_content() 获取文章的全部内容。
strip_shortcodes() 移除文章内容中的简码。
strip_tags() 移除 HTML 标签。
wp_trim_words() 根据单词的数量截取字符串,并添加省略号。
excerpt_length 过滤器,用于修改摘要的长度。
excerpt_more 过滤器,用于修改省略号。
get_the_excerpt 过滤器,用于修改摘要的内容。
the_excerpt 过滤器,用于修改最终输出的摘要内容。

9. 总结的总结:the_excerpt() 的价值

the_excerpt() 函数虽然看起来简单,但它在 WordPress 主题开发中扮演着重要的角色。它提供了一种灵活的方式来显示文章的摘要,并且可以通过过滤器进行自定义。 掌握 the_excerpt() 函数的原理和使用方法,可以帮助开发者更好地控制文章的显示效果,提升用户体验。

好了,今天的 the_excerpt() 源码剖析就到这里。希望大家有所收获,下次再见!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注