register_meta()WP 3.3.0

Registers a meta key (key of custom field).

Registration of a meta-field is needed to use it in different API, for example for REST API. Or you can use this registry to add fields to the meta box: add_meta_box().

It is recommended to register meta keys for a specific combination of object type and object subtype. If passing an object subtype is omitted, the meta key will be registered for the entire object type, however it can be partly overridden in case a more specific meta key of the same name exists for the same object type and a subtype.

If an object type does not support any subtypes, such as users or comments, you should commonly call this function without passing a subtype.

This function behaves a bit like register_post_type(). The data is stored in the global $wp_meta_keys variable. This will allow you to get the meta-field data anywhere in the engine, making it convenient to extend your code.

Registration to a global variable is only available since WP 4.6. The implication is that the feature and the technology implies will start to be used universally from WordPress 4.6.

Hooks from the function

Returns

true|false.

  • true - if the meta-key was successfully registered in the global $wp_meta_keys array.
  • false - if it failed to register the key.

Usage

register_meta( $object_type, $meta_key, $args, $deprecated );
$object_type(string) (required)
The object type for which the meta key is registered: post, user, comment, term. It is a parameter $meta_type from such functions (add/get/update/delete)_metadata( $meta_type, ...)
$meta_key(string) (required)
The name of the key to be registered.
$args(array) (required)

Data describing the meta-field. The defaults are:

$args = array(
	'object_subtype'    => '',
	'type'              => 'string',
	'description'       => '',
	'default'           => '',       // WP 5.5
	'single'            => false,
	'sanitize_callback' => null,
	'auth_callback'     => null,
	'show_in_rest'      => false,
);
  • object_subtype(string) (from version 4.9.8)
    The exact type of the object for which the meta-key is being registered. For example, if $object_type = post, then here you can specify the name of the post type for which the meta-field is registered. If this parameter is left blank, then the meta-field will be registered for all $object_type.
    Default setting: ''

  • type(string).
    The type of the meta field value. The type must be specified without abbreviation:

    • string
    • boolean
    • integer
    • number.
    • array (WP 5.3)
    • object (WP 5.3)

    Default: string

  • description(string)
    A description of the data placed in the meta field. So you can read and understand what is stored here.
    Default: ''

  • single(logical)
    true - there can be only one meta-field with this name.
    false - there can be several such meta-fields.
    Default: false

  • default(string) (WP 5.5)
    Default value returned by get_metadata() if not already set. If more than one meta-key is used, the default value is used for the first entry. In other words, when calling get_metadata() with $single=false parameter, the value set here will be wrapped in an array.
    Default: ''

  • sanitize_callback(string)
    Name of the function or method that will be used when sanitizing the meta-field value during saving it to DB. The specified callback will be added to the filter: sanitize_{$object_type}_meta_{$meta_key}.

    The callback will get three parameters: $meta_value, $meta_key, $object_type. For more details see the code of the function sanitize_meta().

    Default: null

  • auth_callback(string)
    A function or method to call when performing edit_post_meta, add_post_meta, and delete_post_meta capability checks. The specified function will be added to the filter: auth_(object_type)_meta_(meta_key).

    The function must return true or false, which will mean to allow or deny the corresponding action to the user. If you do not specify a function, all users with permission to edit meta-field will automatically get permission to create or delete meta-field.

    The callback receive six parameters:

    function my_callback( $false, $meta_key, $post_id, $user_id, $cap, $caps ){
    	// your check
    }

    For details, see code of map_meta_cap() function.

    See filters:

    Default: null (__return_true)

  • show_in_rest(logical)
    Should this data be shown in REST queries. Whether the data of this meta-field is public.
    Default: false
$deprecated(string/array)
Obsolete since WP 4.6. Use $args instead.
Default: null

Examples

15

#1 Registration of a meta-field for a specific post type

Since WordPress 4.9.8, this feature supports registering metadata not only for the entire object type (records, terms, comments, users), but also for a specific subtype (such as a specific post or taxonomy type). To do this, use the object_subtype parameter:

register_meta( 'post', 'my_meta_key', array(
	'object_subtype' => 'my_post_type',
	'show_in_rest' => true,
	'sanitize_callback' => 'absint',
) );

The specified meta-field will now be considered a meta-field of post type my_post_type and no other post type.

In the same way, you can register a meta-field for a post type, with register_post_meta():

register_post_meta( 'my_post_type', 'my_meta_key', array(
	'show_in_rest' => true,
	'sanitize_callback' => 'absint',
) );

register_post_meta() is a wrapper function and is designed to make registering a meta-field easier and more understandable.

1

#2 Demo

First, let's register the meta-field and see what was added to the global array:

register_meta( 'post', 'bookname', array(
	'type'              => 'string',
	'description'       => 'Название книги',
	'single'            => true,
	'sanitize_callback' => null,
	'auth_callback'     => null,
	'show_in_rest'      => false,
) );

global $wp_meta_keys;

print_r( $wp_meta_keys );

/*
Array
(
	[post] => Array
		(
			[bookname] => Array
				(
					[type] => string
					[description] => Book title
					[single] => 1
					[sanitize_callback] =>
					[auth_callback] => __return_true
					[show_in_rest] =>
				)

		)
)
*/
0

#3 Registering a meta-field

Now let's register a meta-field with access and cleanup functions and check how it works:

register_meta( 'post', 'bookname', array(
	'type'              => 'string',
	'description'       => 'Book title',
	'single'            => true,
	'sanitize_callback' => 'sanitize_bookname_meta',
	'auth_callback'     => 'auth_bookname_meta',
	'show_in_rest'      => false,
) );

function sanitize_bookname_meta( $meta_value, $meta_key, $object_type ){

	$meta_value = wp_strip_all_tags( $meta_value ); // Delete html tags

	return $meta_value;
}

function auth_bookname_meta( $false, $meta_key, $postID, $user_id, $cap, $caps ){

	// forbid creation and editing of this meta-field for everyone except the admin
	if( ! current_user_can('manage_options') )
		return false;

	return true;
}

As a result, if you go to the post editing page and try to create a meta-field bookname there:

  • If you are logged in as admin, the meta-field will be created.
  • If you are an editor, author, etc. - you will not be able to create this meta-field.

The parameter auth_callback is responsible for this.

Further, if you set a string with HTML tags in the value, they will be cut out when updating.

The parameter sanitize_callback* is responsible for this.

Parameters: type, description, `single in WP 4.6, are only informational and are not used anywhere yet.

Changelog

Since 3.3.0 Introduced.
Since 4.6.0 Modified to support an array of data to attach to registered meta keys. Previous arguments for $sanitize_callback and $auth_callback have been folded into this array.
Since 4.9.8 The $object_subtype argument was added to the arguments array.
Since 5.3.0 Valid meta types expanded to include "array" and "object".
Since 5.5.0 The $default argument was added to the arguments array.
Since 6.4.0 The $revisions_enabled argument was added to the arguments array.
Since 6.7.0 The label argument was added to the arguments array.

register_meta() code WP 6.7.1

function register_meta( $object_type, $meta_key, $args, $deprecated = null ) {
	global $wp_meta_keys;

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

	$defaults = array(
		'object_subtype'    => '',
		'type'              => 'string',
		'label'             => '',
		'description'       => '',
		'default'           => '',
		'single'            => false,
		'sanitize_callback' => null,
		'auth_callback'     => null,
		'show_in_rest'      => false,
		'revisions_enabled' => false,
	);

	// There used to be individual args for sanitize and auth callbacks.
	$has_old_sanitize_cb = false;
	$has_old_auth_cb     = false;

	if ( is_callable( $args ) ) {
		$args = array(
			'sanitize_callback' => $args,
		);

		$has_old_sanitize_cb = true;
	} else {
		$args = (array) $args;
	}

	if ( is_callable( $deprecated ) ) {
		$args['auth_callback'] = $deprecated;
		$has_old_auth_cb       = true;
	}

	/**
	 * Filters the registration arguments when registering meta.
	 *
	 * @since 4.6.0
	 *
	 * @param array  $args        Array of meta registration arguments.
	 * @param array  $defaults    Array of default arguments.
	 * @param string $object_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
	 *                            or any other object type with an associated meta table.
	 * @param string $meta_key    Meta key.
	 */
	$args = apply_filters( 'register_meta_args', $args, $defaults, $object_type, $meta_key );
	unset( $defaults['default'] );
	$args = wp_parse_args( $args, $defaults );

	// Require an item schema when registering array meta.
	if ( false !== $args['show_in_rest'] && 'array' === $args['type'] ) {
		if ( ! is_array( $args['show_in_rest'] ) || ! isset( $args['show_in_rest']['schema']['items'] ) ) {
			_doing_it_wrong( __FUNCTION__, __( 'When registering an "array" meta type to show in the REST API, you must specify the schema for each array item in "show_in_rest.schema.items".' ), '5.3.0' );

			return false;
		}
	}

	$object_subtype = ! empty( $args['object_subtype'] ) ? $args['object_subtype'] : '';
	if ( $args['revisions_enabled'] ) {
		if ( 'post' !== $object_type ) {
			_doing_it_wrong( __FUNCTION__, __( 'Meta keys cannot enable revisions support unless the object type supports revisions.' ), '6.4.0' );

			return false;
		} elseif ( ! empty( $object_subtype ) && ! post_type_supports( $object_subtype, 'revisions' ) ) {
			_doing_it_wrong( __FUNCTION__, __( 'Meta keys cannot enable revisions support unless the object subtype supports revisions.' ), '6.4.0' );

			return false;
		}
	}

	// If `auth_callback` is not provided, fall back to `is_protected_meta()`.
	if ( empty( $args['auth_callback'] ) ) {
		if ( is_protected_meta( $meta_key, $object_type ) ) {
			$args['auth_callback'] = '__return_false';
		} else {
			$args['auth_callback'] = '__return_true';
		}
	}

	// Back-compat: old sanitize and auth callbacks are applied to all of an object type.
	if ( is_callable( $args['sanitize_callback'] ) ) {
		if ( ! empty( $object_subtype ) ) {
			add_filter( "sanitize_{$object_type}_meta_{$meta_key}_for_{$object_subtype}", $args['sanitize_callback'], 10, 4 );
		} else {
			add_filter( "sanitize_{$object_type}_meta_{$meta_key}", $args['sanitize_callback'], 10, 3 );
		}
	}

	if ( is_callable( $args['auth_callback'] ) ) {
		if ( ! empty( $object_subtype ) ) {
			add_filter( "auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}", $args['auth_callback'], 10, 6 );
		} else {
			add_filter( "auth_{$object_type}_meta_{$meta_key}", $args['auth_callback'], 10, 6 );
		}
	}

	if ( array_key_exists( 'default', $args ) ) {
		$schema = $args;
		if ( is_array( $args['show_in_rest'] ) && isset( $args['show_in_rest']['schema'] ) ) {
			$schema = array_merge( $schema, $args['show_in_rest']['schema'] );
		}

		$check = rest_validate_value_from_schema( $args['default'], $schema );
		if ( is_wp_error( $check ) ) {
			_doing_it_wrong( __FUNCTION__, __( 'When registering a default meta value the data must match the type provided.' ), '5.5.0' );

			return false;
		}

		if ( ! has_filter( "default_{$object_type}_metadata", 'filter_default_metadata' ) ) {
			add_filter( "default_{$object_type}_metadata", 'filter_default_metadata', 10, 5 );
		}
	}

	// Global registry only contains meta keys registered with the array of arguments added in 4.6.0.
	if ( ! $has_old_auth_cb && ! $has_old_sanitize_cb ) {
		unset( $args['object_subtype'] );

		$wp_meta_keys[ $object_type ][ $object_subtype ][ $meta_key ] = $args;

		return true;
	}

	return false;
}