深入解读 WordPress `register_taxonomy()` 函数源码:分类法信息如何添加到 `$wp_taxonomies`。

嘿,各位代码狂魔,欢迎来到今天的WordPress源码解剖课堂!今天我们要攻克的堡垒是register_taxonomy()函数,看看它如何把分类法信息塞进那个神秘的全局变量$wp_taxonomies里。准备好你的咖啡,我们开始吧!

开场白:分类法的江湖地位

在WordPress的世界里,分类法(Taxonomy)就像一棵树的枝干,帮助我们把文章、页面、自定义文章类型组织得井井有条。有了分类法,内容才不会像无头苍蝇一样乱飞,用户也能更容易地找到自己想要的信息。而register_taxonomy()函数,就是那把锋利的斧头,帮我们砍出这些枝干。

第一幕:register_taxonomy()函数概览

首先,我们来认识一下register_taxonomy()函数的基本结构。它长这样:

function register_taxonomy( string $taxonomy, string|array $object_type, array|string $args = array() ): WP_Taxonomy|WP_Error {
  // 函数体内容
}

看起来是不是很眼熟?这货接受三个参数:

  1. $taxonomy:分类法的名称,比如’category’,’post_tag’,或者你自己定义的’genre’。这就像给分类法起个响亮的名号,以后就靠它行走江湖了。
  2. $object_type:与分类法相关联的文章类型,可以是’post’,’page’,或者你自定义的’movie’。这就像告诉分类法,它是哪个帮派的,以后只管这些文章类型。
  3. $args:一个数组,包含各种各样的选项,控制分类法的行为,比如是否显示在管理界面,是否允许层级关系等等。这就像给分类法定制装备,让它更强大。

而它的返回值,要么是一个WP_Taxonomy对象,代表成功注册的分类法,要么是一个WP_Error对象,告诉你哪里出了问题。

第二幕:源码解读,抽丝剥茧

接下来,我们深入register_taxonomy()的源码,看看它是如何一步步工作的:

function register_taxonomy( string $taxonomy, string|array $object_type, array|string $args = array() ): WP_Taxonomy|WP_Error {
    global $wp_taxonomies;

    // 1. 参数校验和整理
    if ( ! is_string( $taxonomy ) ) {
        return new WP_Error( 'invalid_taxonomy', __( 'Taxonomy names must be strings.' ) );
    }

    if ( strlen( $taxonomy ) > 32 ) {
        return new WP_Error( 'invalid_taxonomy', __( 'Taxonomy names must not exceed 32 characters in length.' ) );
    }

    $taxonomy = sanitize_key( $taxonomy );

    if ( empty( $taxonomy ) ) {
        return new WP_Error( 'invalid_taxonomy', __( 'Taxonomy names must not be empty.' ) );
    }

    if ( ! is_string( $object_type ) && ! is_array( $object_type ) ) {
        return new WP_Error( 'invalid_object_type', __( 'Object types must be strings or arrays.' ) );
    }

    // 2. 默认参数设置
    $default_args = array(
        'labels' => array(),
        'public' => true,
        'show_ui' => true,
        'show_in_menu' => true,
        'show_in_nav_menus' => true,
        'show_tagcloud' => true,
        'show_admin_column' => false,
        'hierarchical' => false,
        'query_var' => $taxonomy,
        'rewrite' => true,
        'capabilities' => array(),
        'meta_box_cb' => null,
        'show_admin_column' => false,
        'description' => '',
        'sort' => null,
        '_builtin' => false,
    );

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

    // 3. 创建 WP_Taxonomy 对象
    $wp_taxonomy = new WP_Taxonomy( $taxonomy, $object_type, $args );

    // 4. 注册分类法到全局变量 $wp_taxonomies
    $wp_taxonomies[ $taxonomy ] = $wp_taxonomy;

    // 5. 关联分类法到文章类型
    if ( is_array( $object_type ) ) {
        foreach ( $object_type as $type ) {
            register_taxonomy_for_object_type( $taxonomy, $type );
        }
    } else {
        register_taxonomy_for_object_type( $taxonomy, $object_type );
    }

    // 6. 返回 WP_Taxonomy 对象
    return $wp_taxonomy;
}

让我们把这段代码分成几个部分来解读:

1. 参数校验和整理

首先,函数会检查传入的参数是否合法,比如分类法名称是否是字符串,长度是否超过32个字符,是否为空等等。如果发现问题,会返回一个WP_Error对象,告诉你哪里出错了。

    if ( ! is_string( $taxonomy ) ) {
        return new WP_Error( 'invalid_taxonomy', __( 'Taxonomy names must be strings.' ) );
    }

    if ( strlen( $taxonomy ) > 32 ) {
        return new WP_Error( 'invalid_taxonomy', __( 'Taxonomy names must not exceed 32 characters in length.' ) );
    }

    $taxonomy = sanitize_key( $taxonomy );

    if ( empty( $taxonomy ) ) {
        return new WP_Error( 'invalid_taxonomy', __( 'Taxonomy names must not be empty.' ) );
    }

    if ( ! is_string( $object_type ) && ! is_array( $object_type ) ) {
        return new WP_Error( 'invalid_object_type', __( 'Object types must be strings or arrays.' ) );
    }

这些检查就像保安一样,确保只有合格的分类法才能进入WordPress的殿堂。sanitize_key()函数会将分类法名称转换成安全的格式,防止潜在的安全问题。

2. 默认参数设置

接下来,函数会设置一些默认参数,如果没有在$args参数中指定,就使用这些默认值。

    $default_args = array(
        'labels' => array(),
        'public' => true,
        'show_ui' => true,
        'show_in_menu' => true,
        'show_in_nav_menus' => true,
        'show_tagcloud' => true,
        'show_admin_column' => false,
        'hierarchical' => false,
        'query_var' => $taxonomy,
        'rewrite' => true,
        'capabilities' => array(),
        'meta_box_cb' => null,
        'show_admin_column' => false,
        'description' => '',
        'sort' => null,
        '_builtin' => false,
    );

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

wp_parse_args()函数会将用户传入的$args参数和默认参数合并,如果用户指定了某个参数,就使用用户的值,否则使用默认值。这就像餐厅里的自助餐,你可以选择自己喜欢的菜,如果没有,就吃厨师准备好的。

这里列出一些重要的参数:

参数名 描述 默认值
labels 一个数组,包含各种标签,用于在管理界面显示,比如’name’,’singular_name’,’search_items’等等。 空数组
public 是否公开分类法,如果为true,则可以在前台页面显示。 true
show_ui 是否在管理界面显示分类法。 true
show_in_menu 是否在管理菜单中显示分类法。 true
hierarchical 是否允许层级关系,如果为true,则可以像分类目录一样有父子关系,如果为false,则像标签一样是扁平的。 false
query_var 用于查询分类法的查询变量,默认为分类法的名称。 $taxonomy
rewrite 是否启用URL重写,如果为true,则可以使用更友好的URL,比如/genre/action而不是/?genre=action true
show_admin_column 是否在文章列表页面显示分类法列,方便快速编辑。 false

3. 创建 WP_Taxonomy 对象

现在,所有的参数都准备好了,函数会创建一个WP_Taxonomy对象,把这些参数都塞进去。

    $wp_taxonomy = new WP_Taxonomy( $taxonomy, $object_type, $args );

WP_Taxonomy类是WordPress专门用来表示分类法的,它包含了分类法的所有信息,比如名称,关联的文章类型,各种选项等等。这就像给分类法颁发了一个身份证,证明它是一个合法的公民。

4. 注册分类法到全局变量 $wp_taxonomies

关键时刻到了!函数会将刚刚创建的WP_Taxonomy对象注册到全局变量$wp_taxonomies中。

    global $wp_taxonomies;
    $wp_taxonomies[ $taxonomy ] = $wp_taxonomy;

$wp_taxonomies是一个全局数组,存储了所有注册的分类法。在这里,函数会将分类法的名称作为键,WP_Taxonomy对象作为值,存储到这个数组中。

这就像把分类法的名字刻在名人墙上,让WordPress知道它的存在。以后,WordPress就可以通过这个全局变量来访问和管理这些分类法了。

5. 关联分类法到文章类型

接下来,函数会将分类法和文章类型关联起来,告诉WordPress,这个分类法是属于哪个文章类型的。

    if ( is_array( $object_type ) ) {
        foreach ( $object_type as $type ) {
            register_taxonomy_for_object_type( $taxonomy, $type );
        }
    } else {
        register_taxonomy_for_object_type( $taxonomy, $object_type );
    }

register_taxonomy_for_object_type()函数会将分类法和文章类型的关系存储起来,方便以后查询和使用。

这就像给分类法贴上标签,告诉大家它是属于哪个帮派的。以后,WordPress就可以根据这些标签来过滤和显示文章。

6. 返回 WP_Taxonomy 对象

最后,函数会返回刚刚创建的WP_Taxonomy对象,方便调用者使用。

    return $wp_taxonomy;

这就像把分类法的身份证还给它,让它可以自由地行走江湖了。

第三幕:$wp_taxonomies 变量的结构

现在,让我们来仔细看看$wp_taxonomies变量的结构。它是一个全局数组,以分类法名称为键,WP_Taxonomy对象为值。

global $wp_taxonomies;
print_r($wp_taxonomies);

// 输出结果示例:
Array
(
    [category] => WP_Taxonomy Object
        (
            [name] => category
            [object_type] => Array
                (
                    [0] => post
                )

            [label] => 分类目录
            [labels] => Array
                (
                    [name] => 分类目录
                    [singular_name] => 分类目录
                    [search_items] => 搜索分类目录
                    [all_items] => 所有分类目录
                    [parent_item] => 父级分类目录
                    [parent_item_colon] => 父级分类目录:
                    [edit_item] => 编辑分类目录
                    [view_item] => 查看分类目录
                    [update_item] => 更新分类目录
                    [add_new_item] => 添加新分类目录
                    [new_item_name] => 新分类目录名称
                    [separate_items_with_commas] => 用逗号分隔分类目录
                    [add_or_remove_items] => 添加或移除分类目录
                    [choose_from_most_used] => 从最常用的分类目录中选择
                    [not_found] => 未找到分类目录。
                    [no_terms] => 没有分类目录。
                    [menu_name] => 分类目录
                    [filter_by_item] => 按分类目录筛选
                    [items_list_navigation] => 分类目录列表导航
                    [items_list] => 分类目录列表
                    [most_used] => Most Used
                    [back_to_items] => ← Back to Categories
                    [item] => Category
                    [new_item] => New Category
                )

            [description] =>
            [public] => 1
            [show_ui] => 1
            [show_in_menu] => 1
            [show_in_nav_menus] => 1
            [show_tagcloud] => 1
            [show_in_quick_edit] =>
            [show_admin_column] => 1
            [hierarchical] => 1
            [update_count_callback] => _update_post_term_count
            [query_var] => category
            [rewrite] => Array
                (
                    [slug] => category
                    [with_front] => 1
                    [hierarchical] =>
                    [ep_mask] => 8192
                    [feed] =>
                    [pages] =>
                )

            [capabilities] => Array
                (
                    [manage_terms] => manage_categories
                    [edit_terms] => edit_categories
                    [delete_terms] => delete_categories
                    [assign_terms] => assign_categories
                )

            [_builtin] => 1
            [_edit_link] => edit-tags.php?action=edit&taxonomy=
        )

    [post_tag] => WP_Taxonomy Object
    (
      // ... 更多分类法
    )
)

可以看到,$wp_taxonomies数组中存储了所有的分类法,每个分类法都是一个WP_Taxonomy对象,包含了分类法的各种信息。

第四幕:实战演练,代码示例

现在,让我们通过一个代码示例来演示如何使用register_taxonomy()函数:

function register_movie_genre() {
  $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' => 'genre' ),
  );

  register_taxonomy( 'genre', 'movie', $args );
}
add_action( 'init', 'register_movie_genre', 0 );

这段代码定义了一个名为register_movie_genre()的函数,用于注册一个名为’genre’的分类法,用于管理电影类型。

  1. 首先,定义了一个$labels数组,包含了各种标签,用于在管理界面显示。
  2. 然后,定义了一个$args数组,包含了各种选项,比如是否允许层级关系,是否在管理界面显示等等。
  3. 最后,调用register_taxonomy()函数,将分类法注册到WordPress中。

add_action( 'init', 'register_movie_genre', 0 );这行代码会在WordPress初始化时调用register_movie_genre()函数,确保分类法在第一时间被注册。

这样,我们就成功地创建了一个自定义分类法’genre’,用于管理电影类型。你可以在管理界面的“文章”菜单下找到“电影类型”菜单,添加和管理电影类型。

第五幕:总结与思考

今天,我们深入解读了register_taxonomy()函数的源码,了解了它是如何把分类法信息添加到$wp_taxonomies全局变量中的。

总结一下:

  1. register_taxonomy()函数接受三个参数:分类法名称,文章类型,选项数组。
  2. 函数会首先校验参数,然后设置默认参数。
  3. 函数会创建一个WP_Taxonomy对象,把参数都塞进去。
  4. 函数会将WP_Taxonomy对象注册到$wp_taxonomies全局变量中。
  5. 函数会将分类法和文章类型关联起来。
  6. 函数会返回WP_Taxonomy对象。

$wp_taxonomies变量是一个全局数组,存储了所有注册的分类法,每个分类法都是一个WP_Taxonomy对象。

通过今天的学习,相信你对WordPress的分类法机制有了更深入的了解。以后,你就可以更加灵活地使用register_taxonomy()函数,创建自定义分类法,管理你的内容了。

希望今天的讲座对你有所帮助。下次再见!

发表回复

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