Using register_meta In WordPress

Using register_meta In WordPress

WordPress provides filters for sanitizing and authenticating your custom post meta. These filters have been around since 3.3 — and until now — were unknown to me. I happened to be reading Tadlock’s content-type-standards repository on Github and noticed some references to register_meta().

What Is register_meta?

The register_meta() function was added in WordPress 3.3 and will simplify adding sanitize and authentication callbacks for your custom meta.  By calling this function and providing callbacks, it will handle appending your callbacks to the appropriate filters.

Let’s take a look at the function.

// WordPress core function: wp-includes/meta.php

/**
 * Register meta key
 *
 * @since 3.3.0
 *
 * @param string       $meta_type         Type of meta
 * @param string       $meta_key          Meta key
 * @param string|array $sanitize_callback A function or method to call when sanitizing the value of $meta_key.
 * @param string|array $auth_callback     Optional. A function or method to call when performing edit_post_meta, add_post_meta, and delete_post_meta capability checks.
 */
function register_meta( $meta_type, $meta_key, $sanitize_callback, $auth_callback = null ) {

    if ( is_callable( $sanitize_callback ) ) {
        add_filter( "sanitize_{$meta_type}_meta_{$meta_key}", $sanitize_callback, 10, 3 );
    }

    if ( empty( $auth_callback ) ) {
        if ( is_protected_meta( $meta_key, $meta_type ) ) {
            $auth_callback = '__return_false';
        } else {
            $auth_callback = '__return_true';
        }
    }

    if ( is_callable( $auth_callback ) ) {
        add_filter( "auth_{$meta_type}_meta_{$meta_key}", $auth_callback, 10, 6 );
    }

}

The function has four parameters; One being optional.

  • $meta_type This is the type of meta. Most of the time this will be `post`, unless you are working with a custom meta table.
  • $meta_key The meta key.
  • $sanitize_callback The meta value will run through the sanitize callback function before saving.
  • $auth_callback If provided, the meta will be hidden from Custom Fields meta box with the post editor. This has the same affect as pre-pending the meta key name with an underscore.

A simple example

Here is a simple example for registering a meta key.

add_action( 'init', 'register_my_sample_meta' );
/**
 * Callback for WordPress 'init' action.
 *
 * Register the post meta.
 *
 * @uses register_meta()
 * @see https://codex.wordpress.org/Function_Reference/register_meta
 */
function register_my_sample_meta() {

    register_meta(
        'post',
        'sample_count',
        'sanitize_sample_count_meta',
        'auth_sample_count_meta'
    );

}

Simply calling register_meta() within a callback for init will suffice. My sample meta key will be sample_count.

Optional sanitize callback

I wish I had knowledge of this filter as it would have saved me time. If you save post meta in more than one place, there is a good chance you have duplicate code. Using this filter allows meta value to be sanitized in once place and reduce that sneaky duplicate code.

/**
 * Callback for WordPress register_meta() sanitize parameter.
 *
 * Sanitize the 'sample_count' meta value before saved to the database.
 *
 * @see https://codex.wordpress.org/Function_Reference/register_meta
 * 
 * @uses absint()
 * @see https://codex.wordpress.org/Function_Reference/absint
 * 
 * @param  mixed  $meta_value The meta value.
 * @param  string $meta_key   The meta key.
 * @param  string $meta_type  The meta type.
 *
 * @return mixed              The meta value.
 */
function sanitize_sample_count_meta( $meta_value, $meta_key, $meta_type ) {

    return absint( $meta_value );

}

Optional authentication callback

In WordPress, you can pre-pend your meta keys with an underscore to prevent them from being visible within the Custom Fields meta box. This prevents all users from the ability to see the meta values in the Custom Fields meta box.

This callback determines who sees what within the Custom Fields meta box. This allows your meta keys to not have the pre-pended underscore. My example allows administrators to see the meta value.

/**
 * Callback for WordPress register_meta() sanitize parameter.
 *
 * Determine if the current meta key and value should be visible within the 
 * WordPress post editor Custom Fields meta box.
 * 
 * @see https://codex.wordpress.org/Function_Reference/register_meta
 *
 * @uses current_user_can()
 * @see https://codex.wordpress.org/Function_Reference/current_user_can
 * 
 * @param  boolean $allowed  True if allowed to view the meta field by default, false if else.
 * @param  string  $meta_key The meta key.
 * @param  integer $post_ID  The post ojbect ID.
 * @param  integer $user_id  The user ID.
 * @param  string  $cap      The meta capability.
 * @param  array   $caps     An array of capabilities.
 * 
 * @return boolean           True if allowed to view the meta field by default, false if else.
 */
function auth_sample_count_meta( $allowed, $meta_key, $post_ID, $user_id, $cap, $caps ) {

    if ( ! current_user_can( 'edit_others_posts' ) ) {
        $allowed = false;
    }

    return $allowed;

}

Remember, this is optional.

All Together Now

Here is the full example. The sanitize callback is what I find to be the biggest advantage here. The custom authentication is your choice.

add_action( 'init', 'register_my_sample_meta' );
/**
 * Callback for WordPress 'init' action.
 *
 * Register the post meta.
 *
 * @uses register_meta()
 * @see https://codex.wordpress.org/Function_Reference/register_meta
 */
function register_my_sample_meta() {

    register_meta(
        'post',
        'sample_count',
        'sanitize_sample_count_meta',
        'auth_sample_count_meta'
    );

}

/**
 * Callback for WordPress register_meta() sanitize parameter.
 *
 * Sanitize the 'sample_count' meta value before saved to the database.
 *
 * @see https://codex.wordpress.org/Function_Reference/register_meta
 * 
 * @uses absint()
 * @see https://codex.wordpress.org/Function_Reference/absint
 * 
 * @param  mixed  $meta_value The meta value.
 * @param  string $meta_key   The meta key.
 * @param  string $meta_type  The meta type.
 *
 * @return mixed              The meta value.
 */
function sanitize_sample_count_meta( $meta_value, $meta_key, $meta_type ) {

    return absint( $meta_value );

}

/**
 * Callback for WordPress register_meta() sanitize parameter.
 *
 * Determine if the current meta key and value should be visible within the 
 * WordPress post editor Custom Fields meta box.
 * 
 * @see https://codex.wordpress.org/Function_Reference/register_meta
 *
 * @uses current_user_can()
 * @see https://codex.wordpress.org/Function_Reference/current_user_can
 * 
 * @param  boolean $allowed  True if allowed to view the meta field by default, false if else.
 * @param  string  $meta_key The meta key.
 * @param  integer $post_ID  The post ojbect ID.
 * @param  integer $user_id  The user ID.
 * @param  string  $cap      The meta capability.
 * @param  array   $caps     An array of capabilities.
 *
 * @return boolean           True if allowed to view the meta field by default, false if else.
 */
function auth_sample_count_meta( $allowed, $meta_key, $post_ID, $user_id, $cap, $caps ) {

    if ( ! current_user_can( 'edit_others_posts' ) ) {
        $allowed = false;
    }

    return $allowed;

}

Author: rfmeier

Product developer at WPEngine and runner from Schaumburg, Illinois. I work with php and Python; Spending most of my time digging into source code to see how it all works.