分析 WordPress `post_type_link` 过滤器源码:如何自定义文章类型的永久链接。

各位观众老爷们,今天咱们就来唠唠 WordPress 里一个神奇的钩子——post_type_link,看看它怎么能让咱们的文章链接变得与众不同,充满个性。准备好,咱们要开始今天的“链接大改造”之旅了!

故事的开始:WordPress 默认的“土味”链接

WordPress 默认的文章链接,尤其是自定义文章类型的链接,有时候显得有些“土味”,比如 http://example.com/?post_type=book&p=123,或者 http://example.com/book/a-brief-history-of-time/。虽然能用,但总觉得少了点味道,不够性感。

这时候,post_type_link 钩子就派上用场了。它允许我们拦截 WordPress 生成文章链接的过程,然后按照我们自己的想法,重新定义链接的格式。

post_type_link 钩子:链接改造的“幕后黑手”

post_type_link 钩子位于 wp-includes/link-template.php 文件中(别害怕,不用真的打开这个文件),它的作用是在 WordPress 生成文章类型链接时,提供一个自定义链接的机会。

简单来说,当 WordPress 想要生成一个文章类型的链接时,它会先检查有没有人“监听” post_type_link 这个“广播”,如果有,就会把相关信息传递给“监听者”,然后“监听者”就可以根据这些信息,返回一个自定义的链接。

post_type_link 钩子的“真面目”

post_type_link 钩子的原型如下:

apply_filters( 'post_type_link', string $post_link, WP_Post $post, bool $leavename, bool $sample )

让我们来逐个击破这些参数:

  • $post_link (string): 这是 WordPress 默认生成的链接,如果没有人干预,它就会是最终的链接。
  • $post (WP_Post): 这是一个 WP_Post 对象,包含了文章的所有信息,比如标题、ID、作者等等。
  • $leavename (bool): 这个参数表示是否保留文章的名称。如果为 true,则在生成链接时会保留文章的名称(slug)。
  • $sample (bool): 这个参数表示是否是“示例链接”(比如在编辑文章时预览链接)。

如何“监听” post_type_link 广播?

要使用 post_type_link 钩子,我们需要使用 add_filter() 函数。这个函数的作用就是告诉 WordPress,我们要“监听”某个“广播”,并且提供一个函数,用于处理接收到的信息。

add_filter( 'post_type_link', 'my_custom_post_type_link', 10, 4 );

function my_custom_post_type_link( $post_link, $post, $leavename, $sample ) {
    // 在这里编写我们的自定义链接逻辑
    return $post_link; // 默认情况下,返回原始链接
}

上面的代码中:

  • add_filter( 'post_type_link', 'my_custom_post_type_link', 10, 4 ):这行代码告诉 WordPress,我们要“监听” post_type_link 广播,并且使用 my_custom_post_type_link 函数来处理接收到的信息。10 是优先级,4 是传递给函数的参数数量(也就是上面说的四个参数)。
  • my_custom_post_type_link( $post_link, $post, $leavename, $sample ):这是我们自定义的函数,用于处理链接生成逻辑。目前它只是简单地返回原始链接,所以没有任何效果。

改造链接:让你的文章链接“闪闪发光”

现在,让我们来真正地改造链接。假设我们有一个自定义文章类型 book,我们希望它的链接格式是 http://example.com/books/年份/书名/

add_filter( 'post_type_link', 'my_custom_book_link', 10, 2 ); // 注意这里只传递了两个参数

function my_custom_book_link( $post_link, $post ) {
    if ( $post->post_type == 'book' ) {
        $year = date( 'Y', strtotime( $post->post_date ) );
        $post_link = home_url( '/books/' . $year . '/' . $post->post_name . '/' );
    }
    return $post_link;
}

这段代码做了以下事情:

  1. 检查文章类型:首先,我们检查文章的类型是否是 book。只有当文章类型是 book 时,我们才进行链接改造,否则就返回原始链接。
  2. 获取年份:我们使用 date() 函数从文章的发布日期中提取年份。
  3. 构建自定义链接:我们使用 home_url() 函数获取网站的根 URL,然后拼接上 /books/年份/书名/ 这样的格式。
  4. 返回自定义链接:最后,我们返回构建好的自定义链接。

注意:

  • 我们这里只传递了两个参数 $post_link$post,因为我们只需要这两个参数就足够完成任务了。
  • $post->post_name 获取的是文章的 slug,也就是文章的“别名”。

别忘了:刷新固定链接!

修改了链接结构后,一定要去 WordPress 后台的“设置 -> 固定链接”页面,点击“保存更改”按钮,刷新一下固定链接。否则,WordPress 可能无法正确地识别新的链接结构。

进阶:使用自定义字段

除了年份,我们还可以使用自定义字段来构建链接。假设我们为 book 文章类型添加了一个自定义字段 author,我们希望链接格式是 http://example.com/books/作者/书名/

add_filter( 'post_type_link', 'my_custom_book_link_with_author', 10, 2 );

function my_custom_book_link_with_author( $post_link, $post ) {
    if ( $post->post_type == 'book' ) {
        $author = get_post_meta( $post->ID, 'author', true );
        if ( $author ) {
            $post_link = home_url( '/books/' . $author . '/' . $post->post_name . '/' );
        }
    }
    return $post_link;
}

这段代码和之前的代码类似,只是多了一个步骤:使用 get_post_meta() 函数获取 author 自定义字段的值。

注意:

  • get_post_meta( $post->ID, 'author', true ) 的第三个参数 true 表示我们只获取单个值。
  • 如果 author 自定义字段为空,我们仍然会返回原始链接。

完善:处理分页

如果你的文章类型支持分页,那么你还需要处理分页链接。post_type_link 钩子不会自动处理分页,你需要手动添加分页参数。

add_filter( 'post_type_link', 'my_custom_book_link_with_pagination', 10, 2 );

function my_custom_book_link_with_pagination( $post_link, $post ) {
    if ( $post->post_type == 'book' ) {
        $year = date( 'Y', strtotime( $post->post_date ) );
        $post_link = home_url( '/books/' . $year . '/' . $post->post_name . '/' );

        // 处理分页
        global $wp_rewrite;
        $paged = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;
        if ( $paged > 1 ) {
            $post_link = trailingslashit( $post_link ) . $wp_rewrite->pagination_base . '/' . $paged . '/';
        }
    }
    return $post_link;
}

这段代码做了以下事情:

  1. 获取分页参数:我们使用 get_query_var( 'paged' ) 函数获取当前的分页参数。
  2. 构建分页链接:如果当前是分页页面($paged > 1),我们就拼接上分页参数。

注意:

  • trailingslashit() 函数用于在链接末尾添加斜杠。
  • $wp_rewrite->pagination_base 是 WordPress 的分页基础 URL,默认为 page

总结:post_type_link 钩子的“十八般武艺”

post_type_link 钩子是一个非常强大的工具,它可以让你自定义文章类型的永久链接,让你的网站链接更加个性化和 SEO 友好。

功能 描述 示例代码 场景 代码示例
基本链接改造 “`php add_filter( ‘post_type_link’, ‘my_custom_post_type_link’, 10, 2 );

function my_custom_post_type_link( $post_link, $post ) {
if ( $post->post_type == ‘book’ ) {
$post_link = home_url( ‘/books/’ . $post->post_name . ‘/’ );
}
return $post_link;
}


| 添加年份        | ```php                                                                      add_filter( 'post_type_link', 'my_custom_book_link', 10, 2 );
function my_custom_book_link( $post_link, $post ) {
    if ( $post->post_type == 'book' ) {
        $year = date( 'Y', strtotime( $post->post_date ) );
        $post_link = home_url( '/books/' . $year . '/' . $post->post_name . '/' );
    }
    return $post_link;
}
```                                                                                |
| 使用自定义字段    | ```php                                                                      add_filter( 'post_type_link', 'my_custom_book_link_with_author', 10, 2 );
function my_custom_book_link_with_author( $post_link, $post ) {
    if ( $post->post_type == 'book' ) {
        $author = get_post_meta( $post->ID, 'author', true );
        if ( $author ) {
            $post_link = home_url( '/books/' . $author . '/' . $post->post_name . '/' );
        }
    }
    return $post_link;
}
```                                                                                |
| 处理分页        | ```php                                                                      add_filter( 'post_type_link', 'my_custom_book_link_with_pagination', 10, 2 );
function my_custom_book_link_with_pagination( $post_link, $post ) {
    if ( $post->post_type == 'book' ) {
        $year = date( 'Y', strtotime( $post->post_date ) );
        $post_link = home_url( '/books/' . $year . '/' . $post->post_name . '/' );

        global $wp_rewrite;
        $paged = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;
        if ( $paged > 1 ) {
            $post_link = trailingslashit( $post_link ) . $wp_rewrite->pagination_base . '/' . $paged . '/';
        }
    }
    return $post_link;
}
```                                                                                |

希望今天的“链接大改造”之旅对你有所帮助。记住,大胆尝试,发挥你的想象力,让你的 WordPress 网站链接变得独一无二!

### 友情提示:

*   在修改链接结构之前,最好备份一下你的网站,以防万一。
*   修改链接结构后,要记得更新你的网站地图,以便搜索引擎能够正确地索引你的网站。
*   谨慎使用 `post_type_link` 钩子,过度修改链接结构可能会影响 SEO。

好啦,今天的讲座就到这里,下课!

发表回复

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