WordPress源码深度解析之:`WordPress`的`custom post type`:`register_post_type()`的底层实现。

咳咳,各位观众老爷们,晚上好!今天咱就来聊聊WordPress里一个相当重要的角色——Custom Post Type(自定义文章类型),以及它背后的功臣——register_post_type()函数。

一、自定义文章类型:WordPress的变形金刚

话说,WordPress最初设计时,就是为了博客而生的。但随着互联网的发展,各种各样的网站需求冒了出来,比如作品集、商品展示、活动等等。如果都用默认的“文章”来搞,那可就乱套了。

这时候,Custom Post Type就派上用场了。它可以让你像变形金刚一样,把WordPress变成任何你想要的样子,比如:

  • 电影: 你可以创建一个“电影”的Custom Post Type,包含导演、演员、上映时间等字段。
  • 书籍: 你可以创建一个“书籍”的Custom Post Type,包含作者、出版社、ISBN等字段。
  • 产品: 你可以创建一个“产品”的Custom Post Type,包含价格、描述、库存等字段。

总而言之,Custom Post Type就是让你在WordPress里创建自己专属的内容类型,让你的网站更加灵活、专业。

二、register_post_type():定义Custom Post Type的魔法棒

要创建Custom Post Type,就得用到register_post_type()这个函数。它就像一根魔法棒,挥一挥,就能变出一个新的文章类型。

它的基本语法是这样的:

register_post_type( string $post_type, array|string $args = array() )
  • $post_type:这是你要创建的Custom Post Type的名称,必须是小写字母,不能包含空格,最多20个字符。比如 ‘movie’、’book’、’product’。
  • $args:这是一个数组,包含了Custom Post Type的各种参数,比如标签、图标、是否支持评论等等。

三、$args:Custom Post Type的灵魂

$args数组里的参数非常多,咱们挑几个常用的、重要的来说:

  • labels:标签

    这个数组定义了Custom Post Type在后台显示的各种标签,比如“添加电影”、“编辑电影”等等。如果不设置,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( '添加电影', 'movie' ),
        'add_new_item'       => __( '添加新电影' ),
        'new_post'           => __( '新电影' ),
        'edit_item'          => __( '编辑电影' ),
        'view_item'          => __( '查看电影' ),
        'all_items'          => __( '所有电影' ),
        'search_items'       => __( '搜索电影' ),
        'parent_item_colon'  => __( '父级电影:' ),
        'not_found'          => __( '没有找到电影。' ),
        'not_found_in_trash' => __( '回收站里没有电影。' )
    );

    注意: 这里用到了_x()__()函数,这是WordPress的国际化函数,用于翻译文本。

  • public:是否公开

    这个参数决定了Custom Post Type是否在前端显示,以及是否可以通过URL访问。

    • true:公开,可以在前端显示,可以通过URL访问。
    • false:不公开,只能在后台管理。
    'public'              => true,
  • exclude_from_search:是否从搜索结果中排除

    这个参数决定了Custom Post Type是否出现在搜索结果中。

    • true:从搜索结果中排除。
    • false:出现在搜索结果中。
    'exclude_from_search' => false,
  • publicly_queryable:是否可以通过URL查询

    这个参数决定了Custom Post Type是否可以通过URL访问。

    • true:可以通过URL访问。
    • false:不能通过URL访问。
    'publicly_queryable'  => true,
  • show_ui:是否显示在后台界面

    这个参数决定了Custom Post Type是否在后台管理界面显示。

    • true:显示在后台管理界面。
    • false:不显示在后台管理界面。
    'show_ui'             => true,
  • show_in_menu:是否在后台菜单中显示

    这个参数决定了Custom Post Type是否在后台菜单中显示。

    • true:在后台菜单中显示。
    • false:不在后台菜单中显示。

    也可以传入一个字符串,表示Custom Post Type显示在哪个菜单项下。比如 'show_in_menu' => 'edit.php?post_type=page' 表示显示在“页面”菜单下。

    'show_in_menu'        => true,
  • show_in_nav_menus:是否在导航菜单中显示

    这个参数决定了Custom Post Type是否可以在导航菜单中添加。

    • true:可以在导航菜单中添加。
    • false:不能在导航菜单中添加。
    'show_in_nav_menus'   => true,
  • show_in_admin_bar:是否在后台管理栏中显示

    这个参数决定了Custom Post Type是否在后台管理栏中显示“新建”按钮。

    • true:在后台管理栏中显示。
    • false:不在后台管理栏中显示。
    'show_in_admin_bar'   => true,
  • menu_position:菜单位置

    这个参数决定了Custom Post Type在后台菜单中的位置。数字越小,位置越靠前。

    'menu_position'       => 5, // 5 is below Posts
  • menu_icon:菜单图标

    这个参数决定了Custom Post Type在后台菜单中显示的图标。可以使用Dashicons,也可以使用自定义的图片URL。

    'menu_icon'           => 'dashicons-format-video',
  • capability_type:权限类型

    这个参数决定了Custom Post Type的权限类型。

    • post:使用默认的文章权限。
    • page:使用默认的页面权限。
    • movie:使用自定义的权限,需要配合capabilities参数使用。
    'capability_type'     => 'post',
  • supports:支持的功能

    这个参数决定了Custom Post Type支持哪些功能,比如标题、正文、摘要、特色图像等等。

    'supports'            => array( 'title', 'editor', 'excerpt', 'thumbnail', 'comments', 'revisions', 'custom-fields', ),

    常用的功能有:

    • title:标题
    • editor:正文
    • excerpt:摘要
    • thumbnail:特色图像
    • comments:评论
    • revisions:修订版本
    • custom-fields:自定义字段
    • page-attributes:页面属性(用于设置父页面和页面模板)
    • post-formats:文章形式
  • taxonomies:分类法

    这个参数决定了Custom Post Type可以使用哪些分类法,比如分类、标签等等。

    'taxonomies'          => array( 'category', 'post_tag' ),
  • has_archive:是否启用文章归档

    这个参数决定了Custom Post Type是否启用文章归档页面。

    • true:启用文章归档页面,可以通过your-domain.com/movie/访问。
    • false:不启用文章归档页面。
    'has_archive'         => true,
  • rewrite:重写规则

    这个参数决定了Custom Post Type的URL重写规则。

    'rewrite'             => array( 'slug' => 'movies' ),

    slug参数指定了Custom Post Type的URL别名。

  • query_var:查询变量

    这个参数决定了Custom Post Type的查询变量名称。

    • true:使用Custom Post Type的名称作为查询变量。
    • false:不使用查询变量。
    • string:使用指定的字符串作为查询变量。
    'query_var'           => true,
  • can_export:是否可以导出

    这个参数决定了Custom Post Type是否可以导出。

    • true:可以导出。
    • false:不能导出。
    'can_export'          => true,
  • show_in_rest:是否在REST API中显示

    这个参数决定了Custom Post Type是否在REST API中显示。

    • true:在REST API中显示。
    • false:不在REST API中显示。
    'show_in_rest'        => true,

四、一个完整的例子

add_action( 'init', 'create_movie_post_type' );
function create_movie_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( '添加电影', 'movie' ),
        'add_new_item'       => __( '添加新电影' ),
        'new_post'           => __( '新电影' ),
        'edit_item'          => __( '编辑电影' ),
        'view_item'          => __( '查看电影' ),
        'all_items'          => __( '所有电影' ),
        'search_items'       => __( '搜索电影' ),
        'parent_item_colon'  => __( '父级电影:' ),
        'not_found'          => __( '没有找到电影。' ),
        'not_found_in_trash' => __( '回收站里没有电影。' )
    );

    $args = array(
        'labels'             => $labels,
        'public'             => true,
        'exclude_from_search' => false,
        'publicly_queryable'  => true,
        'show_ui'             => true,
        'show_in_menu'        => true,
        'show_in_nav_menus'   => true,
        'show_in_admin_bar'   => true,
        'menu_position'       => 5,
        'menu_icon'           => 'dashicons-format-video',
        'capability_type'     => 'post',
        'supports'            => array( 'title', 'editor', 'excerpt', 'thumbnail', 'comments', 'revisions', 'custom-fields', ),
        'taxonomies'          => array( 'category', 'post_tag' ),
        'has_archive'         => true,
        'rewrite'             => array( 'slug' => 'movies' ),
        'query_var'           => true,
        'can_export'          => true,
        'show_in_rest'        => true,
    );

    register_post_type( 'movie', $args );
}

这段代码会在WordPress里创建一个名为“电影”的Custom Post Type。它有自己的后台管理界面,支持标题、正文、摘要、特色图像、评论、修订版本和自定义字段,可以使用分类和标签,有文章归档页面,URL别名为“movies”,可以在REST API中显示。

五、register_post_type()的底层实现:探秘WordPress的内核

好了,说了这么多,咱们来扒一扒register_post_type()的底层实现,看看WordPress是怎么把Custom Post Type变出来的。

register_post_type()函数位于wp-includes/post.php文件中。它的主要功能是:

  1. 验证参数: 检查传入的$post_type$args是否合法。
  2. 注册文章类型: 将Custom Post Type的信息存储到全局变量$wp_post_types中。
  3. 注册分类法: 如果Custom Post Type指定了分类法,则注册这些分类法。
  4. 刷新重写规则: 如果Custom Post Type启用了文章归档页面或指定了URL别名,则刷新WordPress的重写规则。

咱们来简化一下代码,看看register_post_type()的核心逻辑:

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

    // 1. 验证参数
    if ( ! is_string( $post_type ) || empty( $post_type ) ) {
        return new WP_Error( 'invalid_post_type', __( 'Invalid post type name.' ) );
    }

    // 2. 注册文章类型
    $wp_post_types[ $post_type ] = (object) $args; // Simplification: In reality WP_Post_Type object is created
    $wp_post_types[ $post_type ]->name = $post_type;

    // 3. 注册分类法 (Simplified)
    if ( ! empty( $args['taxonomies'] ) ) {
        foreach ( $args['taxonomies'] as $taxonomy ) {
            register_taxonomy_for_object_type( $taxonomy, $post_type );
        }
    }

    // 4. 刷新重写规则 (Simplified)
    $wp_rewrite->flush_rules();
}

可以看到,register_post_type()的核心就是把Custom Post Type的信息存储到全局变量$wp_post_types中。这个变量是一个数组,包含了所有已注册的Custom Post Type的信息。

六、$wp_post_types:Custom Post Type的大本营

$wp_post_types是一个全局变量,它是一个关联数组,键是Custom Post Type的名称,值是一个对象,包含了Custom Post Type的各种属性。

你可以通过以下方式访问$wp_post_types

global $wp_post_types;
print_r( $wp_post_types );

你会看到一个包含所有已注册的Custom Post Type信息的数组。

七、总结

Custom Post Type是WordPress非常强大的功能,它可以让你创建自己专属的内容类型,让你的网站更加灵活、专业。register_post_type()函数是创建Custom Post Type的魔法棒,它把Custom Post Type的信息存储到全局变量$wp_post_types中。

希望今天的讲座能让你对Custom Post Type和register_post_type()有更深入的了解。

下次再见!

发表回复

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