深入理解 `register_taxonomy()` 函数的源码,它是如何将分类法信息添加到 `Array` 全局变量的?

大家好!欢迎来到今天的“WordPress 分类法解剖课”。 今天咱们要深入到 WordPress 的心脏,扒一扒 register_taxonomy() 这个老伙计的底裤,看看它究竟是如何把分类法的信息偷偷塞到全局变量 Array 里的。准备好了吗?系好安全带,咱们要开始了!

第一幕:register_taxonomy() 的前世今生

register_taxonomy() 函数,顾名思义,就是用来注册分类法的。 咱们先来回忆一下它的基本用法:

register_taxonomy(
    string   $taxonomy,
    string|array $object_type,
    array    $args = array()
);
  • $taxonomy: 分类法的名称,比如 ‘category’ (分类) 或者 ‘post_tag’ (标签)。
  • $object_type: 与分类法关联的对象类型,比如 ‘post’ (文章) 或者 ‘page’ (页面)。
  • $args: 一个包含各种配置选项的数组,比如是否是分层结构 (hierarchical)、是否显示在菜单中等等。

第二幕:全局变量,幕后黑手

WordPress 的全局变量,就像一个巨大的公共储物柜,各种信息都往里塞。 而 register_taxonomy() 主要涉及的全局变量有:

  • $wp_taxonomies: 这是一个数组,存储着所有已注册的分类法对象。每个分类法都以其名称作为键,对应一个 WP_Taxonomy 类的实例。
  • $wp_object_types: 也是一个数组,存储了分类法与对象类型的关系。这个全局变量比较少直接看到,但内部起到关键作用。

第三幕:源码探秘,抽丝剥茧

现在,让我们深入到 register_taxonomy() 的源码中,看看它是如何操作这些全局变量的。以下是简化版的 register_taxonomy() 流程(基于 WordPress 6.x 的源码):

  1. 参数校验与标准化:

    函数首先会对传入的参数进行各种校验,确保分类法名称合法、对象类型存在等等。同时,会对 $args 数组进行标准化,设置一些默认值。

    function register_taxonomy( $taxonomy, $object_type, $args = array() ) {
        global $wp_taxonomies, $wp_object_types; // 注意!这里声明了全局变量
    
        // 1. 参数校验
        if ( ! is_string( $taxonomy ) || '' === $taxonomy ) {
            _doing_it_wrong( __FUNCTION__, __( 'Taxonomy names must be strings.' ), '3.0' );
            return new WP_Error( 'invalid_taxonomy', __( 'Taxonomy names must be strings.' ) );
        }
    
        // ... (其他校验代码) ...
    
        // 2. 参数标准化
        $args = wp_parse_args( $args ); // 合并用户传入的 $args 和默认值
    
        // ... (更多参数处理) ...
  2. 创建 WP_Taxonomy 对象:

    接下来,函数会创建一个 WP_Taxonomy 类的实例,并将分类法的各种信息(名称、对象类型、配置选项)存储在这个对象中。

        // 3. 创建 WP_Taxonomy 对象
        $wp_taxonomies[ $taxonomy ] = new WP_Taxonomy( $taxonomy, $object_type, $args );
    
        // ...
  3. 更新 $wp_taxonomies 全局变量:

    最关键的一步来了! 函数将刚刚创建的 WP_Taxonomy 对象,以分类法名称为键,存储到 $wp_taxonomies 全局变量中。 注意,global $wp_taxonomies; 声明了 register_taxonomy() 函数可以访问和修改全局变量 $wp_taxonomies

        // 4. 更新 $wp_taxonomies 全局变量
        $wp_taxonomies[ $taxonomy ] = new WP_Taxonomy( $taxonomy, $object_type, $args );

    这就相当于把分类法的信息放到了公共储物柜里,供 WordPress 的其他部分使用。

  4. 更新 $wp_object_types 全局变量:

    register_taxonomy() 还会更新 $wp_object_types 变量,建立分类法和对象类型之间的关联。 这部分代码稍微复杂一些,因为它要处理一个分类法与多个对象类型关联的情况。

        // 5. 更新 $wp_object_types 全局变量
        foreach ( (array) $object_type as $type ) {
            if ( ! isset( $wp_object_types[ $type ] ) ) {
                $wp_object_types[ $type ] = array();
            }
            $wp_object_types[ $type ][] = $taxonomy;
        }

    这段代码遍历所有与该分类法关联的对象类型,然后将分类法名称添加到对应对象类型的数组中。 这样,WordPress 就能知道哪些分类法与哪些对象类型相关联。

第四幕:WP_Taxonomy 类,分类法的容器

WP_Taxonomy 类是 WordPress 用来表示分类法的核心类。 它包含了分类法的各种属性和方法。 咱们来看看它的主要属性:

属性名称 描述
name 分类法的名称,比如 ‘category’。
object_type 与分类法关联的对象类型,比如 ‘post’。
label 分类法的标签,用于在后台界面显示。
labels 一个包含各种标签的数组,比如 ‘name’ (分类法名称)、’singular_name’ (单数名称)、’edit_item’ (编辑项目) 等等。
description 分类法的描述。
public 是否公开,决定了分类法是否可以在前端访问。
hierarchical 是否是分层结构,决定了分类法是否可以像分类一样有父子关系。
rewrite 一个包含重写规则的数组,决定了分类法的 URL 结构。
query_var 用于查询分类法数据的查询变量名称。
show_admin_column 是否在文章列表页面显示分类法的管理列。

WP_Taxonomy 类还包含一些方法,用于获取和设置分类法的属性,以及执行一些与分类法相关的操作。

第五幕:代码示例,一睹真容

为了更好地理解 register_taxonomy() 的工作原理,咱们来看一个具体的代码示例:

function my_custom_taxonomy() {
    $labels = array(
        'name'              => _x( '电影类型', 'taxonomy general name' ),
        'singular_name'     => _x( '电影类型', 'taxonomy singular name' ),
        'search_items'      => __( '搜索电影类型' ),
        'all_items'         => __( '所有电影类型' ),
        'parent_item'       => __( '父级电影类型' ),
        'parent_item_colon' => __( '父级电影类型:' ),
        'edit_item'         => __( '编辑电影类型' ),
        'update_item'       => __( '更新电影类型' ),
        'add_new_item'      => __( '添加新电影类型' ),
        'new_item_name'     => __( '新电影类型名称' ),
        'menu_name'         => __( '电影类型' ),
    );

    $args = array(
        'hierarchical'      => true,
        'labels'            => $labels,
        'show_ui'           => true,
        'show_admin_column' => true,
        'query_var'         => true,
        'rewrite'           => array( 'slug' => 'movie_genre' ),
    );

    register_taxonomy( 'movie_genre', 'post', $args );
}
add_action( 'init', 'my_custom_taxonomy', 0 );

这段代码定义了一个名为 movie_genre 的自定义分类法,用于对电影文章进行分类。它指定了分类法的各种标签和配置选项,并将其与 post 对象类型关联。

当 WordPress 执行这段代码时,register_taxonomy() 函数会将 movie_genre 分类法的相关信息存储到 $wp_taxonomies$wp_object_types 全局变量中。 这样,WordPress 就能知道存在一个名为 movie_genre 的分类法,并且它与 post 对象类型相关联。

第六幕:幕后花絮,深入挖掘

  • 插件中的分类法: 插件通常会在插件文件中使用 register_taxonomy() 注册自定义分类法。为了确保分类法在 WordPress 初始化完成后注册,插件通常会将 register_taxonomy() 函数挂载到 init 动作钩子上,并设置一个较低的优先级(比如 0 或 1)。
  • 主题中的分类法: 主题也可以注册自定义分类法,但通常不建议这样做。因为当主题被切换时,分类法也会随之消失,导致数据丢失。 最好将自定义分类法放在插件中,以确保数据的持久性。
  • 性能考量: 注册过多的分类法可能会影响 WordPress 的性能,因为每次加载页面时,WordPress 都要加载所有已注册的分类法信息。 因此,应该尽量减少不必要的分类法注册。
  • unregister_taxonomy() 函数:register_taxonomy() 相对应的是 unregister_taxonomy() 函数,用于注销已注册的分类法。 但需要注意的是,注销分类法并不会删除已存在的分类法数据,只是将其从 WordPress 的管理界面中移除。

第七幕:总结与展望

今天,咱们一起深入剖析了 register_taxonomy() 函数的源码,了解了它是如何将分类法信息添加到全局变量 Array 中的。 register_taxonomy() 函数是 WordPress 中一个非常重要的函数,它为我们提供了强大的分类和组织内容的能力。

希望通过今天的讲解,大家对 WordPress 的分类法机制有了更深入的理解。 掌握了这些知识,你就可以更好地利用 WordPress 的分类法功能,构建更灵活、更强大的网站。

下次有机会,我们再一起探讨 WordPress 的其他核心机制! 谢谢大家!

发表回复

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