函数文档

register_post_status()

💡 云策文档标注

概述

register_post_status() 函数用于在 WordPress 中注册或修改文章状态。它接受一个状态名称和可选参数数组,允许开发者自定义状态的行为,如可见性、搜索排除等。必须在 init 钩子后调用,避免过早执行。

关键要点

  • 函数用于创建或修改文章状态,参数包括状态名称和配置数组。
  • 核心参数包括 label(标签)、public(公开性)、internal(内部使用)、exclude_from_search(搜索排除)等,用于控制状态在前后端的表现。
  • 带下划线前缀的参数(如 _builtin)为内部保留,插件和主题不应使用。
  • 状态名称长度限制为 20 字符,超长可能导致保存问题。
  • 注册的状态不会自动出现在文章编辑页面的状态选择中,需额外处理。
  • 文章状态独立于文章类型,全局可用,不存储在选项表中。

代码示例

function wpdocs_custom_post_status(){
    register_post_status( 'unread', array(
        'label'                     => _x( 'Unread', 'post' ),
        'public'                    => true,
        'exclude_from_search'       => false,
        'show_in_admin_all_list'    => true,
        'show_in_admin_status_list' => true,
        'label_count'               => _n_noop( 'Unread (%s)', 'Unread (%s)' ),
    ) );
}
add_action( 'init', 'wpdocs_custom_post_status' );

注意事项

  • 确保在 init 钩子后调用,以避免初始化问题。
  • 状态名称需简洁,避免超过 20 字符限制,以防数据库保存失败。
  • 注册后,状态不会自动显示在编辑界面,可能需要通过过滤或其他方法集成。
  • 参数默认值逻辑复杂,如未指定 public 和 internal 时默认为 internal=true,需仔细测试。

📄 原文内容

Registers a post status. Do not use before init.

Description

A simple function for creating or modifying a post status based on the parameters given. The function will accept an array (second optional parameter), along with a string for the post status name.

Arguments prefixed with an _underscore shouldn’t be used by plugins and themes.

Parameters

$post_statusstringrequired
Name of the post status.
$argsarray|stringoptional
Array or string of post status arguments.

  • label bool|string
    A descriptive name for the post status marked for translation. Defaults to value of $post_status.
  • label_count array|false
    Nooped plural text from _n_noop() to provide the singular and plural forms of the label for counts. Default false which means the $label argument will be used for both the singular and plural forms of this label.
  • exclude_from_search bool
    Whether to exclude posts with this post status from search results. Default is value of $internal.
  • _builtin bool
    Whether the status is built-in. Core-use only.
    Default false.
  • public bool
    Whether posts of this status should be shown in the front end of the site. Default false.
  • internal bool
    Whether the status is for internal use only.
    Default false.
  • protected bool
    Whether posts with this status should be protected.
    Default false.
  • private bool
    Whether posts with this status should be private.
    Default false.
  • publicly_queryable bool
    Whether posts with this status should be publicly- queryable. Default is value of $public.
  • show_in_admin_all_list bool
    Whether to include posts in the edit listing for their post type. Default is the opposite value of $internal.
  • show_in_admin_status_list bool
    Show in the list of statuses with post counts at the top of the edit listings, e.g. All (12) | Published (9) | My Custom Status (2) Default is the opposite value of $internal.
  • date_floating bool
    Whether the post has a floating creation date.
    Default to false.

Default:array()

Return

object

Source

function register_post_status( $post_status, $args = array() ) {
	global $wp_post_statuses;

	if ( ! is_array( $wp_post_statuses ) ) {
		$wp_post_statuses = array();
	}

	// Args prefixed with an underscore are reserved for internal use.
	$defaults = array(
		'label'                     => false,
		'label_count'               => false,
		'exclude_from_search'       => null,
		'_builtin'                  => false,
		'public'                    => null,
		'internal'                  => null,
		'protected'                 => null,
		'private'                   => null,
		'publicly_queryable'        => null,
		'show_in_admin_status_list' => null,
		'show_in_admin_all_list'    => null,
		'date_floating'             => null,
	);
	$args     = wp_parse_args( $args, $defaults );
	$args     = (object) $args;

	$post_status = sanitize_key( $post_status );
	$args->name  = $post_status;

	// Set various defaults.
	if ( null === $args->public && null === $args->internal && null === $args->protected && null === $args->private ) {
		$args->internal = true;
	}

	if ( null === $args->public ) {
		$args->public = false;
	}

	if ( null === $args->private ) {
		$args->private = false;
	}

	if ( null === $args->protected ) {
		$args->protected = false;
	}

	if ( null === $args->internal ) {
		$args->internal = false;
	}

	if ( null === $args->publicly_queryable ) {
		$args->publicly_queryable = $args->public;
	}

	if ( null === $args->exclude_from_search ) {
		$args->exclude_from_search = $args->internal;
	}

	if ( null === $args->show_in_admin_all_list ) {
		$args->show_in_admin_all_list = ! $args->internal;
	}

	if ( null === $args->show_in_admin_status_list ) {
		$args->show_in_admin_status_list = ! $args->internal;
	}

	if ( null === $args->date_floating ) {
		$args->date_floating = false;
	}

	if ( false === $args->label ) {
		$args->label = $post_status;
	}

	if ( false === $args->label_count ) {
		// phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralSingular,WordPress.WP.I18n.NonSingularStringLiteralPlural
		$args->label_count = _n_noop( $args->label, $args->label );
	}

	$wp_post_statuses[ $post_status ] = $args;

	return $args;
}

Changelog

Version Description
3.0.0 Introduced.

User Contributed Notes

  1. Skip to note 5 content

    20 is the maximum character length for the $post_status parameter.

    wp shell<br />
    wp> global $wpdb;<br />
    wp> $wpdb->get_col_length('wp_posts','post_status')<br />
    => phar:///usr/local/bin/wp/vendor/wp-cli/shell-command/src/WP_CLI/Shell/REPL.php:52:<br />
    array(2) {<br />
    'type' =><br />
    string(4) "char"<br />
    'length' =><br />
    int(20)<br />
    }

    We’re able to register a post status with a $post_status parameter longer than 20 characters, but we’re unable to save/update posts with it. Instead, the wpdb->process_fields() method compares the converted data to the provided data and returns false because they’re different.

  2. Skip to note 6 content

    Example
    An example of registering a post status called “Unread”:

    /**
     * Add 'Unread' post status.
     */
    function wpdocs_custom_post_status(){
    	register_post_status( 'unread', array(
    		'label'                     => _x( 'Unread', 'post' ),
    		'public'                    => true,
    		'exclude_from_search'       => false,
    		'show_in_admin_all_list'    => true,
    		'show_in_admin_status_list' => true,
    		'label_count'               => _n_noop( 'Unread <span class="count">(%s)</span>', 'Unread <span class="count">(%s)</span>' ),
    	) );
    }
    add_action( 'init', 'wpdocs_custom_post_status' );

  3. Skip to note 7 content

    Something that was not clear in my understanding was the independent nature of Post Statuses in connection with Custom Post Types (CPT). I had always been under the assumption that a specific Post Status had to be linked to a specific post type, but the reality is that post statuses exist separate or independent from any post type or custom post type.

    From what I can see, the only place where Post Status is declared is within the code. A list of available post statuses can be generated from the global variable

    global  $wp_post_statuses;

    . These different post_status are not stored as list or array in the options table of database. The only place where post_status is used in the database is in the wp_posts table as the actual `post_status` value.

    To load a specific set of post_status values in the post editor screen (for example) is beyond the scope of this comment, but you will want to look into filtering the values for the post_status as is relevant to your needs.

  4. Skip to note 8 content

    It seems that using the register_post_status function doesn’t add the new post status as an option in the edit post page, or quick edit either, which is disappointing. The issue, and some workarounds, is discussed in more detail here:
    https://stackoverflow.com/q/20298346/612253
    Hopefully it will help others avoid wasting as much time on the issue as I did!