解析 WordPress `get_terms_args` 过滤器源码:如何修改 `get_terms()` 函数的查询参数。

各位观众老爷,晚上好!我是你们的老朋友,今天咱们不聊风花雪月,就来扒一扒 WordPress 里面一个非常重要的过滤器:get_terms_args

这个过滤器,就像是 get_terms() 函数的秘密武器,有了它,你可以随心所欲地修改 get_terms() 函数的查询参数,让它按照你的想法去检索分类法(taxonomy)的术语(term)。 听起来是不是很刺激? 别着急,咱们一步一步来,保证让你听得明白,用得溜溜的。

一、 什么是 get_terms(),为什么要修改它的参数?

首先,得简单介绍一下 get_terms() 函数。 get_terms() 是 WordPress 核心提供的一个函数,主要用来获取分类法下的所有术语。 比如,你想获取文章分类(category)下的所有分类,或者标签(tag)下的所有标签,又或者自定义分类法下的所有术语,都可以用它。

为什么要修改它的参数呢? 你想想,默认情况下,get_terms() 获取到的术语可能很多,你可能只想获取特定数量的术语,或者按照特定的顺序排列,或者只获取某个父级分类下的子分类等等。 这时候,就需要修改 get_terms() 的查询参数了。

二、 get_terms_args 过滤器:你的专属修改器

get_terms_args 过滤器就在 get_terms() 函数的核心位置,它允许你拦截并修改传递给 WP_Term_Query 类的参数数组。 你可以把它想象成一个拦截器,在 get_terms() 函数真正执行查询之前,给你一个机会,让你修改查询的条件。

三、 源码剖析:get_terms_args 的真面目

我们来简单看一下 get_terms() 函数的源码片段,找到 get_terms_args 过滤器的身影:

function get_terms( $args = '', $deprecated = '' ) {
    // ...省略一些代码...

    $defaults = array(
        'search'         => '',
        'number'         => '',
        'offset'         => '',
        'orderby'        => 'name',
        'order'          => 'ASC',
        // ...省略其他参数...
    );

    $args = wp_parse_args( $args, $defaults );

    // Filter the query arguments.
    $args = apply_filters( 'get_terms_args', $args, $taxonomies, $args_array );

    $term_query = new WP_Term_Query( $args );

    // ...省略后面的代码...
}

看到了吗? apply_filters( 'get_terms_args', $args, $taxonomies, $args_array ); 这就是 get_terms_args 过滤器发挥作用的地方。

  • 'get_terms_args': 这是过滤器的名称,告诉 WordPress 我们要拦截 get_terms_args 这个过滤器。
  • $args: 这是传递给过滤器的第一个参数,也是最重要的参数。它是一个数组,包含了 get_terms() 函数的所有查询参数。 你可以在这里修改任何你想修改的参数。
  • $taxonomies: 这是第二个参数,一个数组,包含了你要查询的分类法名称。
  • $args_array: 这是原始的参数数组,通常和 $args 相同,但确保提供原始数据。

四、 实战演练:修改 get_terms_args 的正确姿势

现在,我们来通过几个例子,演示如何使用 get_terms_args 过滤器来修改 get_terms() 函数的查询参数。

例子 1:只获取指定数量的术语

假设你想只获取文章分类(category)下的前 5 个分类,你可以这样做:

add_filter( 'get_terms_args', 'my_custom_get_terms_args', 10, 3 );

function my_custom_get_terms_args( $args, $taxonomies, $args_array ) {
    if ( in_array( 'category', $taxonomies ) ) {
        $args['number'] = 5;
    }
    return $args;
}

这段代码的意思是:

  1. 使用 add_filter() 函数,将 my_custom_get_terms_args 函数添加到 get_terms_args 过滤器中。
  2. my_custom_get_terms_args 函数接收三个参数:$args$taxonomies$args_array
  3. in_array( 'category', $taxonomies ) 判断我们要查询的分类法是否是 ‘category’。 只有当我们要查询的是 ‘category’ 时,才修改参数。
  4. $args['number'] = 5;$args 数组中的 ‘number’ 键的值设置为 5。 ‘number’ 参数控制要获取的术语的数量。
  5. return $args; 将修改后的 $args 数组返回。 非常重要! 如果你不返回 $argsget_terms() 函数将无法获取到你修改后的参数。

例子 2:按照术语 ID 排序

假设你想按照术语 ID 的降序排列文章标签(post_tag),你可以这样做:

add_filter( 'get_terms_args', 'my_custom_get_terms_args', 10, 3 );

function my_custom_get_terms_args( $args, $taxonomies, $args_array ) {
    if ( in_array( 'post_tag', $taxonomies ) ) {
        $args['orderby'] = 'term_id';
        $args['order'] = 'DESC';
    }
    return $args;
}

这段代码的逻辑和例子 1 类似,只是修改了 $args 数组中的 ‘orderby’ 和 ‘order’ 键的值。

  • $args['orderby'] = 'term_id'; 将 ‘orderby’ 设置为 ‘term_id’,表示按照术语 ID 排序。
  • $args['order'] = 'DESC'; 将 ‘order’ 设置为 ‘DESC’,表示降序排列。

例子 3:只获取某个父级分类下的子分类

假设你想只获取 ID 为 10 的父级分类下的子分类,你可以这样做:

add_filter( 'get_terms_args', 'my_custom_get_terms_args', 10, 3 );

function my_custom_get_terms_args( $args, $taxonomies, $args_array ) {
    if ( in_array( 'category', $taxonomies ) ) {
        $args['parent'] = 10;
    }
    return $args;
}
  • $args['parent'] = 10; 将 ‘parent’ 设置为 10,表示只获取父级 ID 为 10 的子分类。

例子 4:使用 meta_query 进行更复杂的查询

get_terms() 函数也支持使用 meta_query 来进行更复杂的查询。 假设你想只获取 my_custom_meta 字段的值为 ‘hello’ 的术语,你可以这样做:

add_filter( 'get_terms_args', 'my_custom_get_terms_args', 10, 3 );

function my_custom_get_terms_args( $args, $taxonomies, $args_array ) {
    if ( in_array( 'category', $taxonomies ) ) {
        $args['meta_query'] = array(
            array(
                'key'     => 'my_custom_meta',
                'value'   => 'hello',
                'compare' => '=',
            ),
        );
    }
    return $args;
}

这段代码使用了 meta_query 参数,它是一个数组,可以包含多个 meta 查询条件。

  • 'key' => 'my_custom_meta' 指定要查询的 meta 字段的键名为 ‘my_custom_meta’。
  • 'value' => 'hello' 指定要查询的 meta 字段的值为 ‘hello’。
  • 'compare' => '=' 指定比较运算符为 ‘=’,表示等于。

五、 get_terms_args 过滤器支持的参数

为了方便大家使用,我整理了一个表格,列出了 get_terms_args 过滤器支持的所有参数:

参数名 类型 描述
search string 搜索术语名称。
number int 要获取的术语的数量。 如果设置为 0,则获取所有术语。
offset int 偏移量。 从第几个术语开始获取。
orderby string 排序方式。 可选值:’name’(默认),’slug’,’term_group’,’term_id’,’id’,’description’,’count’,’none’,以及自定义字段的键名(需要使用 meta_key 参数)。
order string 排序顺序。 可选值:’ASC’(默认,升序),’DESC’(降序)。
hide_empty bool 是否隐藏没有文章的术语。 默认为 true。
include array 只获取指定的术语 ID。
exclude array 排除指定的术语 ID。
exclude_tree array 排除指定的术语 ID 及其所有子术语。
slug string/array 只获取指定 slug 的术语。
hierarchical bool 是否获取分层结构的术语。 默认为 true。
name__like string 模糊匹配术语名称。
description__like string 模糊匹配术语描述。
pad_counts bool 是否更新术语的文章数量。 默认为 false。
get string 返回值的类型。 可选值:’all’(默认,返回所有术语对象),’id=>name’(返回 ID=>名称 的关联数组),’count’(返回术语的数量)。
child_of int 只获取指定术语 ID 的子术语。 与 parent 参数类似,但 child_of 会递归获取所有子孙术语。
parent int 只获取指定术语 ID 的直接子术语。
childless bool 只获取没有子术语的术语。
cache_domain string 缓存域。 用于区分不同的缓存。
update_term_meta_cache bool 是否更新术语的 meta 缓存。 默认为 true。
meta_key string 用于排序的自定义字段的键名。 需要与 orderby 参数一起使用。
meta_value string 用于过滤的自定义字段的值。 需要与 meta_key 参数一起使用。
meta_query array 用于进行更复杂的自定义字段查询。 可以包含多个 meta 查询条件。
taxonomy string/array 要查询的分类法名称。 这个参数通常不需要通过 get_terms_args 过滤器修改,因为它是在调用 get_terms() 函数时指定的。
name string 完全匹配术语名称。

六、 注意事项

  • 优先级(priority): add_filter() 函数的第三个参数是优先级。 优先级越低,过滤器执行的越早。 默认优先级是 10。 如果你需要确保你的过滤器在其他过滤器之前执行,可以将优先级设置为一个较小的数字,例如 1。
  • 参数数量(accepted_args): add_filter() 函数的第四个参数是接受的参数数量。 get_terms_args 过滤器接收三个参数,所以你需要将这个参数设置为 3。
  • 返回值: 你的过滤器函数必须返回修改后的 $args 数组。 否则,get_terms() 函数将无法获取到你修改后的参数。
  • 性能: 过度使用 get_terms_args 过滤器可能会影响性能。 尽量只在必要的时候才使用它,并尽量减少过滤器的复杂性。
  • 调试: 如果你发现你的过滤器没有生效,可以使用 var_dump()error_log() 函数来调试 $args 数组,看看你的修改是否正确。

七、 总结

get_terms_args 过滤器是一个非常强大的工具,可以让你灵活地控制 get_terms() 函数的查询行为。 掌握了它,你就可以轻松地实现各种复杂的术语查询需求。

希望今天的讲解对你有所帮助。 记住,实践是检验真理的唯一标准。 多动手,多尝试,你才能真正掌握 get_terms_args 过滤器的使用方法。

下次再见!

发表回复

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