大家好,欢迎来到今天的“WordPress源码解剖”特别讲座!今天我们要扒的是WordPress里一个至关重要的函数:register_post_type()
。这货可是WordPress定义文章类型的核心枢纽,理解它,你就理解了WordPress内容组织的底层逻辑。
准备好了吗?Let’s dive in!
第一部分:register_post_type()
的基本结构与参数
register_post_type()
,顾名思义,就是注册文章类型的函数。 它接受两个主要参数:文章类型名称和一个参数数组。
register_post_type( string $post_type, array|string $args = array() ) : WP_Post_Type|WP_Error
$post_type
(string, required): 文章类型的名称。 注意,这玩意儿必须是小写字母,可以包含数字和下划线,最多20个字符。 比如:'book'
,'event'
,'my_custom_post'
.$args
(array|string, optional): 一个包含各种选项的数组,用于配置文章类型的行为和外观。 也可以传递一个字符串,通常是true
,用于启用默认行为。 默认值是一个空数组array()
。
$args
数组里面可以包含的参数那是相当丰富,我们挑几个常用的说一下:
参数 | 类型 | 描述 | 默认值 |
---|---|---|---|
labels |
array | 一个关联数组,定义用于文章类型界面的各种标签。 | 自动生成 |
public |
bool | 是否公开文章类型。 这决定了文章类型是否在前端可见,是否可以通过搜索找到,等等。 | false |
show_ui |
bool | 是否在 WordPress 管理界面中显示文章类型的界面。 | 根据 public 的值决定 |
rewrite |
bool|array | 控制文章类型的 URL 重写规则。 可以是一个布尔值,表示启用或禁用默认重写规则;也可以是一个数组,用于自定义重写规则。 | true |
supports |
array | 一个数组,指定文章类型支持的功能,例如 title (标题), editor (编辑器), thumbnail (特色图像) 等等。 |
title 和 editor |
hierarchical |
bool | 是否允许文章类型具有父子关系,类似页面。 | false |
taxonomies |
array | 一个数组,指定文章类型关联的分类法。 | 空数组 |
第二部分:源码剖析——深入 register_post_type()
的内部世界
现在,让我们深入 wp-includes/post.php
文件,探究 register_post_type()
的源码,看看它到底做了些什么。
function register_post_type( string $post_type, array|string $args = array() ) : WP_Post_Type|WP_Error {
global $wp_post_types;
// Sanitize the post type name.
$post_type = sanitize_key( $post_type );
if ( empty( $post_type ) ) {
return new WP_Error( 'post_type_length_invalid', __( 'Post type names must be between 1 and 20 characters in length.' ) );
}
if ( strlen( $post_type ) > 20 ) {
return new WP_Error( 'post_type_length_invalid', __( 'Post type names must be between 1 and 20 characters in length.' ) );
}
if ( ! is_array( $args ) ) {
$args = array( 'public' => (bool) $args );
}
$args = wp_parse_args( $args );
if ( isset( $wp_post_types[ $post_type ] ) ) {
/**
* Fires before a post type is registered.
*
* @since 3.0.0
*
* @param string $post_type Post type key.
* @param array $args Array of arguments for registering a post type.
*/
do_action( 'unregister_post_type', $post_type, $args );
return new WP_Error( 'post_type_exists', __( 'Post type already registered.' ) );
}
// Back compat with quirky plugins.
$args['name'] = $post_type;
$post_type_object = new WP_Post_Type( $post_type, $args );
$wp_post_types[ $post_type ] = $post_type_object;
add_post_type_support( $post_type );
/**
* Fires after a post type is registered.
*
* @since 3.0.0
*
* @param string $post_type Post type key.
* @param WP_Post_Type $post_type_object The registered post type object.
*/
do_action( 'registered_post_type', $post_type, $post_type_object );
return $post_type_object;
}
我们来逐行解读一下:
-
global $wp_post_types;
: 声明全局变量$wp_post_types
。这个全局变量是 WordPress 存储所有已注册文章类型对象的地方。 就像一个巨大的文章类型登记簿。 -
$post_type = sanitize_key( $post_type );
: 对文章类型名称进行清理,确保它是一个有效的键名。 这能防止一些恶意代码注入,保证程序的安全性。 -
if ( empty( $post_type ) ) { ... }
和if ( strlen( $post_type ) > 20 ) { ... }
: 对文章类型名称的长度进行验证。 必须在1到20个字符之间。 否则,返回一个WP_Error
对象。 -
if ( ! is_array( $args ) ) { $args = array( 'public' => (bool) $args ); }
: 如果传入的$args
不是数组,则将其转换为一个数组,并将$args
的值赋给'public'
键。 这主要是为了兼容旧版本的代码。 -
$args = wp_parse_args( $args );
: 使用wp_parse_args()
函数将传入的$args
数组与默认参数合并。 这确保了所有必需的参数都被设置,即使它们没有在传入的$args
数组中显式指定。 -
if ( isset( $wp_post_types[ $post_type ] ) ) { ... }
: 检查文章类型是否已经注册。 如果已经注册,则触发unregister_post_type
动作,并返回一个WP_Error
对象。 避免重复注册导致冲突。 -
$args['name'] = $post_type;
: 将文章类型名称赋给$args['name']
。 这主要是为了兼容一些古老的插件。 -
$post_type_object = new WP_Post_Type( $post_type, $args );
: 创建一个WP_Post_Type
类的实例,并将文章类型名称和参数传递给构造函数。WP_Post_Type
类定义了文章类型的属性和方法。 -
$wp_post_types[ $post_type ] = $post_type_object;
: 将新创建的WP_Post_Type
对象存储到全局变量$wp_post_types
中。 这就是文章类型被添加到 WordPress 核心数据结构的关键一步。 -
add_post_type_support( $post_type );
: 为文章类型添加默认的文章类型支持。 -
do_action( 'registered_post_type', $post_type, $post_type_object );
: 触发registered_post_type
动作。 允许其他插件或主题在文章类型注册后执行一些自定义操作。 -
return $post_type_object;
: 返回新创建的WP_Post_Type
对象。
第三部分:WP_Post_Type
类——文章类型的蓝图
WP_Post_Type
类是定义文章类型属性和行为的蓝图。 让我们看看它的重要成员:
属性 | 类型 | 描述 |
---|---|---|
$name |
string | 文章类型的名称。 |
$label |
string | 文章类型的单数名称,用于用户界面。 |
$labels |
object | 一个对象,包含用于文章类型界面的各种标签。 |
$description |
string | 文章类型的描述。 |
$public |
bool | 是否公开文章类型。 |
$show_ui |
bool | 是否在 WordPress 管理界面中显示文章类型的界面。 |
$show_in_menu |
bool | 是否在管理菜单中显示文章类型。 |
$show_in_rest |
bool | 是否在 REST API 中显示文章类型。 |
$rest_base |
string | REST API 的基本路由。 |
$rest_controller_class |
string | REST API 控制器的类名。 |
$show_in_nav_menus |
bool | 是否在导航菜单中显示文章类型。 |
$show_in_admin_bar |
bool | 是否在管理栏中显示文章类型。 |
$menu_position |
int | 文章类型在管理菜单中的位置。 |
$menu_icon |
string | 文章类型在管理菜单中显示的图标。 |
$capability_type |
string|array | 用于文章类型的权限类型。 |
$capabilities |
array | 一个数组,包含文章类型的权限。 |
$map_meta_cap |
bool | 是否将文章类型的权限映射到默认的 WordPress 权限。 |
$hierarchical |
bool | 是否允许文章类型具有父子关系。 |
$supports |
array | 一个数组,指定文章类型支持的功能。 |
$taxonomies |
array | 一个数组,指定文章类型关联的分类法。 |
$has_archive |
bool|string | 是否启用文章类型的存档页面。 |
$rewrite |
bool|array | 控制文章类型的 URL 重写规则。 |
$query_var |
bool|string | 控制文章类型的查询变量。 |
$can_export |
bool | 是否允许导出文章类型。 |
$delete_with_user |
bool | 是否在用户删除时删除文章类型。 |
$_builtin |
bool | 是否是内置的文章类型。 |
$_edit_link |
string | 编辑链接的格式。 |
第四部分: 实践案例——注册一个“电影”文章类型
让我们用一个例子来演示如何使用 register_post_type()
注册一个名为 "movie" 的文章类型。
add_action( 'init', 'create_movie_post_type' );
function create_movie_post_type() {
$labels = array(
'name' => _x( 'Movies', 'post type general name', 'my-theme' ),
'singular_name' => _x( 'Movie', 'post type singular name', 'my-theme' ),
'menu_name' => _x( 'Movies', 'admin menu', 'my-theme' ),
'name_admin_bar' => _x( 'Movie', 'add new on admin bar', 'my-theme' ),
'add_new' => _x( 'Add New', 'movie', 'my-theme' ),
'add_new_item' => __( 'Add New Movie', 'my-theme' ),
'new_item' => __( 'New Movie', 'my-theme' ),
'edit_item' => __( 'Edit Movie', 'my-theme' ),
'view_item' => __( 'View Movie', 'my-theme' ),
'all_items' => __( 'All Movies', 'my-theme' ),
'search_items' => __( 'Search Movies', 'my-theme' ),
'parent_item_colon' => __( 'Parent Movies:', 'my-theme' ),
'not_found' => __( 'No movies found.', 'my-theme' ),
'not_found_in_trash' => __( 'No movies found in Trash.', 'my-theme' )
);
$args = array(
'labels' => $labels,
'public' => true,
'publicly_queryable' => true,
'show_ui' => true,
'show_in_menu' => true,
'query_var' => true,
'rewrite' => array( 'slug' => 'movie' ),
'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( 'movie', $args );
}
这段代码做了以下几件事:
-
add_action( 'init', 'create_movie_post_type' );
: 将create_movie_post_type()
函数挂载到init
动作钩子上。 这意味着该函数将在 WordPress 初始化时被执行。 -
$labels
数组: 定义了用于 "movie" 文章类型的各种标签。 这些标签将在 WordPress 管理界面中使用。 -
$args
数组: 定义了 "movie" 文章类型的各种选项。 例如,'public' => true
表示该文章类型是公开的,'rewrite' => array( 'slug' => 'movie' )
表示该文章类型的 URL slug 是 "movie",'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments' )
表示该文章类型支持标题、编辑器、作者、特色图像、摘要和评论等功能。 -
register_post_type( 'movie', $args );
: 使用register_post_type()
函数注册 "movie" 文章类型。
第五部分:add_post_type_support()
函数
我们之前提到 register_post_type()
函数内部调用了 add_post_type_support()
函数。 这个函数的作用是为文章类型添加默认的文章类型支持。 让我们看看它的源码:
function add_post_type_support( string|array $post_types, string|array ...$features ) : void {
global $_wp_post_type_features;
if ( ! is_array( $post_types ) ) {
$post_types = array( $post_types );
}
foreach ( $post_types as $post_type ) {
if ( ! isset( $_wp_post_type_features[ $post_type ] ) ) {
$_wp_post_type_features[ $post_type ] = array();
}
foreach ( $features as $feature ) {
$_wp_post_type_features[ $post_type ][ $feature ] = true;
}
}
}
global $_wp_post_type_features;
: 声明全局变量$_wp_post_type_features
。 这个全局变量是 WordPress 存储所有文章类型支持的功能的地方。- 类型检查和转换: 确保
$post_types
是一个数组。 - 循环添加特性: 遍历所有指定的文章类型,并为每个文章类型添加所有指定的功能。
第六部分:总结与注意事项
通过今天的讲解,我们深入了解了 register_post_type()
函数的内部机制,以及它如何将新的文章类型添加到 WordPress 的核心数据结构中。 掌握了这个函数,你就可以灵活地定制 WordPress 的内容组织方式,创建各种各样的自定义文章类型,满足你的各种需求。
最后,总结几个注意事项:
- 文章类型名称必须是小写字母,可以包含数字和下划线,最多20个字符。
$args
数组中的参数可以控制文章类型的各种行为和外观。WP_Post_Type
类是定义文章类型属性和行为的蓝图。add_post_type_support()
函数用于为文章类型添加默认的文章类型支持。- 注册文章类型时,要考虑 SEO 优化,合理设置 URL 重写规则。
希望今天的讲座对你有所帮助! 谢谢大家!