详解 WordPress `register_post_type()` 函数源码:文章类型信息如何添加到全局变量。

各位观众老爷们,今天咱们不聊风花雪月,就来啃啃WordPress源码里的硬骨头——register_post_type()函数。这玩意儿可是WordPress的核心之一,它决定了你网站上除了文章和页面之外,还能有什么花样。咱们来扒一扒它怎么把文章类型的信息塞进全局变量里,让整个WordPress都知道你的新玩具。

开场白:WordPress的“注册表”

你可以把WordPress想象成一个大型的游乐场,而register_post_type()就像是游乐场的“注册处”。你想在这个游乐场里增加一个新的游乐设施(比如“产品”、“电影”、“食谱”),那就必须先到注册处登记一下。登记的时候,你要告诉注册处这个游乐设施叫什么名字,长什么样子,有什么功能等等。注册处会把这些信息记录在案,然后告诉整个游乐场,以后大家都知道有这么个新玩意儿了。

这个“注册处”在WordPress里就是register_post_type()函数,而它记录信息的地方,就是WordPress的全局变量。

一、register_post_type()函数概览

首先,咱们来看看register_post_type()函数的庐山真面目。它的基本语法是这样的:

<?php
register_post_type( string $post_type, array|string $args = array() );
?>
  • $post_type:这是你自定义文章类型的名称,必须是小写字母,可以用下划线,但不能用空格。比如productmovierecipe
  • $args:这是一个数组,包含了自定义文章类型的各种参数,比如标签(labels)、支持的功能(supports)、是否公开(public)等等。

二、源码探秘:从函数定义到参数处理

咱们深入到源码里,看看register_post_type()究竟是怎么工作的。以下是简化后的源码片段:

// wp-includes/post.php

function register_post_type( $post_type, $args = array() ) {
    global $wp_post_types;

    if ( ! is_string( $post_type ) || empty( $post_type ) ) {
        _doing_it_wrong( __FUNCTION__, __( 'Post type names must be strings and cannot be empty.' ), '3.0' );
        return new WP_Error( 'invalid-post-type', __( 'Invalid post type.' ) );
    }

    if ( strlen( $post_type ) > 20 ) {
        _doing_it_wrong( __FUNCTION__, __( 'Post type names must not exceed 20 characters in length.' ), '3.0' );
        return new WP_Error( 'invalid-post-type', __( 'Post type names must not exceed 20 characters in length.' ) );
    }

    $post_type = sanitize_key( $post_type );

    if ( isset( $wp_post_types[ $post_type ] ) ) {
        _doing_it_wrong( __FUNCTION__, sprintf( __( 'Post type "%s" has already been registered. You cannot register it again.' ), $post_type ), '3.0' );
        return new WP_Error( 'post-type-exists', sprintf( __( 'Post type "%s" already registered.' ), $post_type ) );
    }

    $args = wp_parse_args( $args, array(
        'labels'                => array(),
        'description'           => '',
        'public'                => false,
        'exclude_from_search'   => null,
        'publicly_queryable'    => null,
        'show_ui'               => null,
        'show_in_menu'          => null,
        'show_in_nav_menus'     => null,
        'show_in_admin_bar'     => null,
        'menu_position'         => null,
        'menu_icon'             => null,
        'capability_type'       => 'post',
        'capabilities'          => array(),
        'map_meta_cap'          => false,
        'hierarchical'          => false,
        'supports'              => array(),
        'register_meta_box_cb'  => '',
        'taxonomies'            => array(),
        'has_archive'           => false,
        'rewrite'               => true,
        'query_var'             => true,
        'can_export'            => true,
        'delete_with_user'      => null,
        '_builtin'              => false,
        '_edit_link'            => 'post.php?post=%d',
    ) );

    $args = (object) $args;

    $post_type_object = new WP_Post_Type( $post_type, $args );

    $wp_post_types[ $post_type ] = $post_type_object;

    /**
     * Fires after a post type is registered.
     *
     * @since 3.3.0
     *
     * @param string       $post_type        Post type key.
     * @param WP_Post_Type $post_type_object Post type object.
     */
    do_action( 'registered_post_type', $post_type, $post_type_object );

    return $post_type_object;
}

咱们一步步来解读:

  1. 全局变量声明:global $wp_post_types;

    这行代码至关重要,它声明了$wp_post_types是一个全局变量。这意味着,在register_post_type()函数内部,我们可以访问和修改这个全局变量。$wp_post_types是一个数组,它用来存储所有已注册的自定义文章类型的信息。

  2. 参数校验:

    函数首先会检查$post_type是否合法。它必须是一个字符串,不能为空,长度不能超过20个字符,并且只能包含小写字母和下划线。如果$post_type不合法,函数会抛出一个错误。

  3. 重复注册检查:

    函数会检查$wp_post_types数组中是否已经存在同名的文章类型。如果已经存在,函数会抛出一个错误,防止重复注册。

  4. 参数默认值处理:wp_parse_args()

    wp_parse_args()函数用于合并用户传入的$args数组和默认参数数组。这样,即使你只传入了部分参数,register_post_type()也能保证所有参数都有值。
    例如,如果你只传入了'public' => true,那么其他参数都会使用默认值。

    $args = wp_parse_args( $args, array(
            'labels'                => array(),
            'description'           => '',
            'public'                => false,
            // ... 更多默认参数
        ) );
  5. 创建WP_Post_Type对象:$post_type_object = new WP_Post_Type( $post_type, $args );

    WP_Post_Type是一个类,它用来表示一个自定义文章类型。register_post_type()函数会根据传入的$post_type$args创建一个WP_Post_Type对象。这个对象包含了自定义文章类型的所有信息。

  6. WP_Post_Type对象存储到全局变量:$wp_post_types[ $post_type ] = $post_type_object;

    这行代码是核心!它将新创建的WP_Post_Type对象存储到全局变量$wp_post_types中。$post_type作为数组的键,WP_Post_Type对象作为数组的值。这样,整个WordPress都可以通过$wp_post_types数组访问到这个自定义文章类型的信息。

  7. 触发registered_post_type动作:do_action( 'registered_post_type', $post_type, $post_type_object );

    这个动作允许其他插件或主题在自定义文章类型注册完成后执行一些操作。你可以通过add_action()函数来监听这个动作。

  8. 返回WP_Post_Type对象:return $post_type_object;

    函数最后返回新创建的WP_Post_Type对象。

三、$wp_post_types全局变量的结构

$wp_post_types是一个数组,它的键是自定义文章类型的名称,值是WP_Post_Type对象。WP_Post_Type对象包含了自定义文章类型的各种属性,比如:

属性名 类型 描述
name string 文章类型名称
label string 文章类型的标签(单数形式)
labels array 文章类型的标签(各种形式,比如“添加新文章”、“编辑文章”等)
description string 文章类型的描述
public bool 是否公开
exclude_from_search bool 是否从搜索结果中排除
publicly_queryable bool 是否可以通过URL访问
show_ui bool 是否在后台显示用户界面
show_in_menu bool 是否在后台菜单中显示
show_in_nav_menus bool 是否在导航菜单中显示
show_in_admin_bar bool 是否在管理工具栏中显示
menu_position int 在后台菜单中的位置
menu_icon string 在后台菜单中的图标
capability_type string 用于权限控制的文章类型
capabilities array 权限控制的详细配置
map_meta_cap bool 是否使用默认的权限映射
hierarchical bool 是否具有层级关系(像页面一样)
supports array 支持的功能(比如“标题”、“内容”、“特色图像”等)
taxonomies array 关联的分类法(比如“分类目录”、“标签”等)
has_archive bool string 是否具有文章归档页面,可以是布尔值,也可以是自定义的归档页面slug
rewrite bool array 是否启用URL重写,可以是布尔值,也可以是包含slugwith_frontfeedspagesep_mask等键的数组
query_var bool string 是否启用查询变量,可以是布尔值,也可以是自定义的查询变量名
can_export bool 是否可以导出
delete_with_user bool null 是否在用户删除时删除文章
_builtin bool 是否是内置的文章类型
_edit_link string 编辑文章的链接

四、代码示例:注册一个“电影”类型的文章

下面是一个简单的例子,演示如何使用register_post_type()函数注册一个名为“movie”的自定义文章类型:

<?php
add_action( 'init', 'create_movie_post_type' );
function create_movie_post_type() {
    register_post_type( 'movie',
        array(
            'labels' => array(
                'name' => __( 'Movies' ),
                'singular_name' => __( 'Movie' )
            ),
            'public' => true,
            'has_archive' => true,
            'rewrite' => array( 'slug' => 'movies' ),
            'supports' => array( 'title', 'editor', 'thumbnail', 'custom-fields' ),
            'menu_icon' => 'dashicons-video-alt'
        )
    );
}
?>

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

  1. add_action( 'init', 'create_movie_post_type' );

    这行代码将create_movie_post_type()函数绑定到init动作上。init动作在WordPress初始化完成后触发。这意味着,当WordPress初始化完成后,create_movie_post_type()函数会被调用,从而注册“movie”类型的文章。

  2. register_post_type( 'movie', ... );

    这行代码调用register_post_type()函数,注册一个名为“movie”的自定义文章类型。

  3. 'labels' => array(...)

    这部分代码定义了“movie”类型的标签。'name'是文章类型的复数形式,'singular_name'是文章类型的单数形式。

  4. 'public' => true

    这行代码设置“movie”类型为公开的,这意味着可以在前台和后台访问它。

  5. 'has_archive' => true

    这行代码启用“movie”类型的文章归档页面。

  6. 'rewrite' => array( 'slug' => 'movies' )

    这行代码设置“movie”类型的URL重写规则。'slug' => 'movies'表示“movie”类型的文章URL将以/movies/开头。

  7. 'supports' => array( 'title', 'editor', 'thumbnail', 'custom-fields' )

    这行代码指定“movie”类型支持的功能。'title'表示支持标题,'editor'表示支持内容编辑器,'thumbnail'表示支持特色图像,'custom-fields'表示支持自定义字段。

  8. 'menu_icon' => 'dashicons-video-alt'

    这行代码设置“movie”类型在后台菜单中的图标。'dashicons-video-alt'表示使用WordPress内置的“视频”图标。

五、如何访问和使用$wp_post_types全局变量

在注册了自定义文章类型之后,你可以在WordPress的任何地方访问和使用$wp_post_types全局变量。例如,你可以使用以下代码获取“movie”类型的WP_Post_Type对象:

<?php
global $wp_post_types;
$movie_post_type = $wp_post_types['movie'];

// 现在你可以访问$movie_post_type对象的属性了
echo $movie_post_type->label; // 输出 "Movie"
echo $movie_post_type->has_archive; // 输出 1 (true)
?>

六、注意事项

  • 注册时间: 确保在init动作中注册自定义文章类型,以确保在WordPress初始化完成后注册。
  • 文章类型名称: 文章类型名称必须是小写字母,可以使用下划线,但不能使用空格,且长度不能超过20个字符。
  • 避免冲突: 尽量选择独特的名字,避免与其他插件或主题的自定义文章类型冲突。
  • 刷新固定链接: 在注册自定义文章类型后,务必刷新固定链接设置,以确保URL重写规则生效。

七、总结:register_post_type()的意义

register_post_type()函数是WordPress的核心函数之一,它允许开发者创建自定义文章类型,从而扩展WordPress的功能。通过深入了解register_post_type()函数的源码,我们可以更好地理解WordPress的内部机制,从而更好地开发WordPress插件和主题。 掌握了register_post_type(),你就掌握了WordPress的“造物权”,可以创造出各种各样的内容类型,满足不同的需求。

希望今天的讲解对你有所帮助。记住,源码就像一本武功秘籍,需要反复研读才能领悟其中的奥妙。 下次再见,祝大家编程愉快!

发表回复

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