深入理解 `register_taxonomy()` 和 `register_post_type()` 函数的源码,分析它们如何将新的分类法和自定义文章类型注册到 WordPress 中。

各位观众老爷,晚上好!今天咱们不聊风花雪月,就来硬核一波,扒一扒 WordPress 底裤里的两个重要函数:register_taxonomy()register_post_type()。 这俩哥们儿,一个是分类法的户口登记员,一个是文章类型的户口登记员,专门负责给新来的分类法和文章类型上户口,让 WordPress 认识它们,并且在后台给它们安排妥妥的展示位置。

咱们的讲座分两部分,先聊 register_taxonomy(),再聊 register_post_type(),最后简单总结一下。

第一部分:深入 register_taxonomy() – 分类法的户口登记员

register_taxonomy() 函数,顾名思义,就是注册分类法的。分类法是什么?简单来说,就是给文章归类的“维度”。 WordPress 内置了两种分类法:category (分类目录) 和 post_tag (标签)。 但有时候,这两种分类法不够用,比如你想做一个“产品”类型的网站,可能需要“产品分类”、“产品标签”等更细致的分类法。 这时候,就需要 register_taxonomy() 出马了。

1. 函数原型:

register_taxonomy(
    string   $taxonomy,
    string|string[] $object_type,
    array    $args = array()
);
  • $taxonomy: (必须) 分类法的名称,必须是小写字母和下划线组成,最多32个字符。 比如:product_categoryevent_tag。 这个名字一旦确定,就不能轻易修改,否则可能会导致数据丢失。
  • $object_type: (必须) 要应用此分类法的文章类型。 可以是一个文章类型的名称(字符串),也可以是一个包含多个文章类型名称的数组。 比如:'post''product'array('post', 'product')
  • $args: (可选) 一个包含各种参数的数组,用于控制分类法的行为和外观。 这个参数非常重要,决定了分类法在后台的显示方式,以及用户如何使用它。

2. $args 参数详解:

$args 参数是 register_taxonomy() 函数的核心,它控制了分类法的各种属性。 咱们挑几个常用的、重要的参数来说说:

  • labels: 一个数组,用于定义分类法在后台显示的各种标签。 比如分类法的名称、添加新分类法的按钮文字等等。 如果不设置,WordPress 会使用默认的标签。

    'labels' => array(
        'name'                       => _x( '产品分类', 'taxonomy general name' ),
        'singular_name'              => _x( '产品分类', 'taxonomy singular name' ),
        'search_items'               => __( '搜索产品分类' ),
        'popular_items'              => __( '常用产品分类' ),
        'all_items'                  => __( '所有产品分类' ),
        'parent_item'                => __( '父级产品分类' ),
        'parent_item_colon'          => __( '父级产品分类:' ),
        'edit_item'                  => __( '编辑产品分类' ),
        'update_item'                => __( '更新产品分类' ),
        'add_new_item'               => __( '添加新产品分类' ),
        'new_item_name'              => __( '新产品分类名称' ),
        'separate_items_with_commas' => __( '使用逗号分隔产品分类' ),
        'add_or_remove_items'        => __( '添加或移除产品分类' ),
        'choose_from_most_used'      => __( '从最常用的产品分类中选择' ),
        'not_found'                  => __( '未找到产品分类' ),
        'menu_name'                  => __( '产品分类' ),
    ),

    这个 labels 数组里的每个键都对应着分类法在后台显示的某个标签。 _x() 函数是 WordPress 的本地化函数,用于翻译文本。

  • public: 一个布尔值,控制分类法是否公开可见。 如果设置为 true,分类法将在前台和后台都可见。 如果设置为 false,分类法只在后台可见。 默认为 true
  • hierarchical: 一个布尔值,控制分类法是否具有层级关系。 如果设置为 true,分类法类似于分类目录,可以有父级分类和子分类。 如果设置为 false,分类法类似于标签,没有层级关系。 默认为 false
  • show_ui: 一个布尔值,控制是否在后台显示分类法的管理界面。 如果设置为 true,将在后台显示分类法的管理界面,允许用户添加、编辑和删除分类法。 如果设置为 false,则不显示管理界面。 默认为 true
  • show_admin_column: 一个布尔值,控制是否在文章列表页面显示分类法的列。 如果设置为 true,将在文章列表页面显示一个列,显示文章所属的分类法。 默认为 false
  • query_var: 一个字符串或布尔值,用于控制分类法的查询变量。 如果设置为一个字符串,该字符串将作为查询变量的名称。 如果设置为 true,WordPress 将使用分类法的名称作为查询变量的名称。 如果设置为 false,将禁用分类法的查询功能。 默认为分类法的名称。
  • rewrite: 一个数组或布尔值,用于控制分类法的 URL 重写规则。 如果设置为一个数组,可以自定义 URL 重写规则。 如果设置为 true,WordPress 将使用默认的 URL 重写规则。 如果设置为 false,将禁用分类法的 URL 重写功能。 默认为 true

    'rewrite' => array(
        'slug'         => 'product-category', // URL slug
        'with_front'   => true,             // 是否在 URL 中包含前缀
        'hierarchical' => true,             // 是否使用层级 URL
    ),

    slug 定义了分类法 URL 的一部分。 with_front 控制是否在 URL 中包含 WordPress 的前缀 (通常是 /blog/)。 hierarchical 控制是否使用层级 URL (比如 /product-category/parent-category/child-category/)。

  • capabilities: 一个数组,用于定义控制分类法访问权限的功能。 可以自定义用户角色可以执行的操作,比如编辑、删除分类法。 如果不设置,WordPress 会使用默认的功能。 这个参数比较高级,一般情况下不需要修改。

3. 示例代码:

下面是一个注册名为 product_category 的分类法的示例代码,用于给 product 文章类型进行分类:

add_action( 'init', 'register_product_category' );
function register_product_category() {
    $labels = array(
        'name'                       => _x( '产品分类', 'taxonomy general name' ),
        'singular_name'              => _x( '产品分类', 'taxonomy singular name' ),
        'search_items'               => __( '搜索产品分类' ),
        'popular_items'              => __( '常用产品分类' ),
        'all_items'                  => __( '所有产品分类' ),
        'parent_item'                => __( '父级产品分类' ),
        'parent_item_colon'          => __( '父级产品分类:' ),
        'edit_item'                  => __( '编辑产品分类' ),
        'update_item'                  => __( '更新产品分类' ),
        'add_new_item'               => __( '添加新产品分类' ),
        'new_item_name'              => __( '新产品分类名称' ),
        'separate_items_with_commas' => __( '使用逗号分隔产品分类' ),
        'add_or_remove_items'        => __( '添加或移除产品分类' ),
        'choose_from_most_used'      => __( '从最常用的产品分类中选择' ),
        'not_found'                  => __( '未找到产品分类' ),
        'menu_name'                  => __( '产品分类' ),
    );

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

    register_taxonomy( 'product_category', 'product', $args );
}

这段代码做了以下几件事:

  1. 使用 add_action() 函数,将 register_product_category() 函数绑定到 init 钩子上。 init 钩子在 WordPress 初始化完成后触发,是注册分类法和文章类型的最佳时机。
  2. 定义了一个 $labels 数组,用于设置分类法在后台显示的各种标签。
  3. 定义了一个 $args 数组,用于设置分类法的各种属性。
  4. 调用 register_taxonomy() 函数,注册名为 product_category 的分类法,并将其应用于 product 文章类型。

4. 源码分析:

虽然我们通常不需要直接修改 WordPress 核心代码,但了解 register_taxonomy() 函数的内部运作机制,可以帮助我们更好地理解分类法的工作原理。

简而言之,register_taxonomy() 函数主要做了以下几件事:

  1. 参数验证: 检查传入的参数是否有效。 比如,分类法名称是否符合规范,文章类型是否存在等等。
  2. 数据存储: 将分类法的各种属性存储到全局变量 $wp_taxonomies 中。 $wp_taxonomies 是一个关联数组,以分类法名称为键,以分类法的属性数组为值。
  3. 钩子触发: 触发 registered_taxonomy 钩子,允许其他插件或主题对分类法进行修改。

表格总结:register_taxonomy() 常用参数

参数名 类型 描述 默认值
labels 数组 定义分类法在后台显示的各种标签。 WordPress
public 布尔值 控制分类法是否公开可见。 true
hierarchical 布尔值 控制分类法是否具有层级关系。 false
show_ui 布尔值 控制是否在后台显示分类法的管理界面。 true
show_admin_column 布尔值 控制是否在文章列表页面显示分类法的列。 false
query_var 字符串/布尔值 控制分类法的查询变量。 分类法名称
rewrite 数组/布尔值 控制分类法的 URL 重写规则。 true
capabilities 数组 定义控制分类法访问权限的功能。 WordPress

第二部分:深入 register_post_type() – 文章类型的户口登记员

register_post_type() 函数,顾名思义,就是注册文章类型的。 文章类型是什么? 简单来说,就是不同类型的文章。 WordPress 内置了两种文章类型:post (文章) 和 page (页面)。 但有时候,这两种文章类型不够用,比如你想做一个“产品”类型的网站,可能需要一个专门的 product 文章类型。 这时候,就需要 register_post_type() 出马了。

1. 函数原型:

register_post_type(
    string $post_type,
    array  $args = array()
);
  • $post_type: (必须) 文章类型的名称,必须是小写字母和下划线组成,最多20个字符。 比如:producteventportfolio_item。 同样,这个名字一旦确定,就不要轻易修改。
  • $args: (可选) 一个包含各种参数的数组,用于控制文章类型的行为和外观。 这个参数非常重要,决定了文章类型在后台的显示方式,以及用户如何使用它。

2. $args 参数详解:

$args 参数是 register_post_type() 函数的核心,它控制了文章类型的各种属性。 咱们挑几个常用的、重要的参数来说说:

  • labels: 一个数组,用于定义文章类型在后台显示的各种标签。 比如文章类型的名称、添加新文章的按钮文字等等。 如果不设置,WordPress 会使用默认的标签。

    'labels' => array(
        'name'               => _x( '产品', 'post type general name' ),
        'singular_name'      => _x( '产品', 'post type singular name' ),
        'menu_name'          => _x( '产品', 'admin menu' ),
        'name_admin_bar'     => _x( '产品', 'add new on admin bar' ),
        'add_new'            => _x( '添加新产品', 'product' ),
        'add_new_item'       => __( '添加新产品' ),
        'new_item'           => __( '新产品' ),
        'edit_item'          => __( '编辑产品' ),
        'view_item'          => __( '查看产品' ),
        'all_items'          => __( '所有产品' ),
        'search_items'       => __( '搜索产品' ),
        'parent_item_colon'  => __( '父级产品:' ),
        'not_found'          => __( '未找到产品' ),
        'not_found_in_trash' => __( '回收站中未找到产品' ),
    ),

    register_taxonomy() 类似,labels 数组定义了文章类型在后台各种地方显示的文字。

  • public: 一个布尔值,控制文章类型是否公开可见。 如果设置为 true,文章类型将在前台和后台都可见。 如果设置为 false,文章类型只在后台可见。 默认为 false。 如果你想让用户在前台看到你的自定义文章类型,一定要设置为 true
  • exclude_from_search: 一个布尔值,控制是否将文章类型排除在搜索结果之外。 如果设置为 true,文章类型将不会出现在搜索结果中。 默认为 false
  • publicly_queryable: 一个布尔值,控制是否可以通过 URL 查询文章类型。 如果设置为 true,可以通过 URL 查询文章类型。 默认为 false
  • show_ui: 一个布尔值,控制是否在后台显示文章类型的管理界面。 如果设置为 true,将在后台显示文章类型的管理界面,允许用户添加、编辑和删除文章。 如果设置为 false,则不显示管理界面。 默认为 false。 如果你想在后台管理你的自定义文章类型,一定要设置为 true
  • show_in_menu: 一个布尔值或字符串,控制是否在后台菜单中显示文章类型。 如果设置为 true,将在后台菜单中显示文章类型。 如果设置为一个字符串,该字符串将作为菜单项的父级菜单。 默认为 false
  • menu_position: 一个整数,控制文章类型在后台菜单中的位置。 数字越小,位置越高。
  • menu_icon: 一个字符串,用于设置文章类型在后台菜单中显示的图标。 可以使用 WordPress 内置的 Dashicons,也可以使用自定义的图标。
  • capability_type: 一个字符串或数组,用于定义控制文章类型访问权限的功能。 可以自定义用户角色可以执行的操作,比如编辑、删除文章。 如果不设置,WordPress 会使用默认的功能。
  • supports: 一个数组,用于定义文章类型支持的功能。 比如标题、内容、编辑器、特色图像、自定义字段等等。

    'supports' => array(
        'title',       // 标题
        'editor',      // 内容编辑器
        'thumbnail',   // 特色图像
        'excerpt',     // 摘要
        'custom-fields', // 自定义字段
        'revisions',   // 版本修订
    ),

    这个 supports 数组告诉 WordPress,我们的 product 文章类型支持哪些功能。 如果你不需要某个功能,可以将其从数组中删除。

  • taxonomies: 一个数组,用于将文章类型与分类法关联起来。 比如,可以将 product 文章类型与 product_categoryproduct_tag 分类法关联起来。
  • has_archive: 一个布尔值或字符串,控制是否为文章类型创建存档页面。 如果设置为 true,WordPress 将使用默认的存档页面。 如果设置为一个字符串,该字符串将作为存档页面的 URL slug。 默认为 false
  • rewrite: 一个数组或布尔值,用于控制文章类型的 URL 重写规则。 如果设置为一个数组,可以自定义 URL 重写规则。 如果设置为 true,WordPress 将使用默认的 URL 重写规则。 如果设置为 false,将禁用文章类型的 URL 重写功能。 默认为 true

    'rewrite' => array(
        'slug'       => 'product',     // URL slug
        'with_front' => true,        // 是否在 URL 中包含前缀
        'pages'      => true,        // 是否支持分页
        'feeds'      => true,        // 是否支持 Feed
    ),

    register_taxonomy() 类似,rewrite 定义了文章类型 URL 的一部分,以及一些其他的 URL 相关的设置。

3. 示例代码:

下面是一个注册名为 product 的文章类型的示例代码:

add_action( 'init', 'register_product_post_type' );
function register_product_post_type() {
    $labels = array(
        'name'               => _x( '产品', 'post type general name' ),
        'singular_name'      => _x( '产品', 'post type singular name' ),
        'menu_name'          => _x( '产品', 'admin menu' ),
        'name_admin_bar'     => _x( '产品', 'add new on admin bar' ),
        'add_new'            => _x( '添加新产品', 'product' ),
        'add_new_item'       => __( '添加新产品' ),
        'new_item'           => __( '新产品' ),
        'edit_item'          => __( '编辑产品' ),
        'view_item'          => __( '查看产品' ),
        'all_items'          => __( '所有产品' ),
        'search_items'       => __( '搜索产品' ),
        'parent_item_colon'  => __( '父级产品:' ),
        'not_found'          => __( '未找到产品' ),
        'not_found_in_trash' => __( '回收站中未找到产品' ),
    );

    $args = array(
        'labels'             => $labels,
        'public'             => true,
        'publicly_queryable' => true,
        'show_ui'            => true,
        'show_in_menu'       => true,
        'query_var'          => true,
        'rewrite'            => array( 'slug' => 'product' ),
        'capability_type'    => 'post',
        'has_archive'        => true,
        'hierarchical'       => false,
        'menu_position'      => null,
        'supports'           => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments' ),
        'taxonomies'          => array( 'category', 'post_tag' ), // 关联默认分类法
    );

    register_post_type( 'product', $args );
}

这段代码和 register_taxonomy() 的示例代码类似,也是通过 add_action() 将函数绑定到 init 钩子上,然后定义 $labels$args 数组,最后调用 register_post_type() 函数注册文章类型。

4. 源码分析:

register_post_type() 函数的内部运作机制与 register_taxonomy() 函数类似,主要做了以下几件事:

  1. 参数验证: 检查传入的参数是否有效。 比如,文章类型名称是否符合规范等等。
  2. 数据存储: 将文章类型的各种属性存储到全局变量 $wp_post_types 中。 $wp_post_types 是一个关联数组,以文章类型名称为键,以文章类型的属性数组为值。
  3. 钩子触发: 触发 registered_post_type 钩子,允许其他插件或主题对文章类型进行修改。

表格总结:register_post_type() 常用参数

参数名 类型 描述 默认值
labels 数组 定义文章类型在后台显示的各种标签。 WordPress
public 布尔值 控制文章类型是否公开可见。 false
exclude_from_search 布尔值 控制是否将文章类型排除在搜索结果之外。 false
publicly_queryable 布尔值 控制是否可以通过 URL 查询文章类型。 false
show_ui 布尔值 控制是否在后台显示文章类型的管理界面。 false
show_in_menu 布尔值/字符串 控制是否在后台菜单中显示文章类型。 false
menu_position 整数 控制文章类型在后台菜单中的位置。 null
menu_icon 字符串 设置文章类型在后台菜单中显示的图标。 null
capability_type 字符串/数组 定义控制文章类型访问权限的功能。 post
supports 数组 定义文章类型支持的功能。 array()
taxonomies 数组 将文章类型与分类法关联起来。 array()
has_archive 布尔值/字符串 控制是否为文章类型创建存档页面。 false
rewrite 数组/布尔值 控制文章类型的 URL 重写规则。 true

总结:

register_taxonomy()register_post_type() 是 WordPress 扩展性的基石。 掌握了这两个函数,就可以创建各种各样的自定义分类法和文章类型,从而打造出功能强大的网站。

  • 相同点: 都是通过 $args 数组来控制行为和外观,都使用 add_action() 绑定到 init 钩子上,都将数据存储到全局变量中,都触发钩子。
  • 不同点: register_taxonomy() 用于注册分类法,register_post_type() 用于注册文章类型。 register_taxonomy()$object_type 参数用于指定分类法应用于哪些文章类型,而 register_post_type()taxonomies 参数用于指定文章类型与哪些分类法关联。

希望今天的讲座能帮助大家更深入地理解 register_taxonomy()register_post_type() 函数。 记住,熟能生巧,多写代码,多实践,才能真正掌握这两个函数。 感谢大家的观看,下次再见!

发表回复

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