Post Meta Generator

Typed meta keys with a sanitiser, an auth callback and a REST schema — so a block, the API and your PHP all read the same value the same way.

post-meta.php
Saved just now
Scope
Registered for post only. 3 of 3 keys exposed to REST, authorised with edit_post on the individual post.
Meta keys
3 keys
singleREST
acme_reading_time
singleREST
acme_subtitle
singleREST
acme_featured
Extras
Helper accessors
A typed get_ function per key, so templates never repeat the string.
Uninstall cleanup
delete_post_meta_by_key() for each key, as an uninstall.php comment.
<?php
// Generated with WP CodeKit — powered by GrowQuest (https://growquest.io).
/**
 * Plugin Name:       post meta
 * Description:       Registers 3 meta keys for post.
 * Version:           1.0.0
 * Requires PHP:      7.4
 * Text Domain:       acme
 */

defined( 'ABSPATH' ) || exit;

/**
 * Who may read and write these keys through the API.
 *
 * @param bool   $allowed Whether the user can act.
 * @param string $meta_key The key.
 * @param int    $post_id  The post.
 * @return bool
 */
function acme_meta_auth( $allowed, $meta_key, $post_id ) {
	return current_user_can( 'edit_post', $post_id );
}

/**
 * Register the meta keys.
 */
function acme_register_meta() {
	register_post_meta(
		'post',
		'acme_reading_time',
		array(
			'type'              => 'integer',
			'single'            => true,
			'description'       => __( 'Estimated reading time in minutes.', 'acme' ),
			'default'           => 0,
			'sanitize_callback' => 'absint',
			'auth_callback'     => 'acme_meta_auth',
			'show_in_rest'      => true,
		)
	);

	register_post_meta(
		'post',
		'acme_subtitle',
		array(
			'type'              => 'string',
			'single'            => true,
			'description'       => __( 'Shown under the title.', 'acme' ),
			'default'           => '',
			'sanitize_callback' => 'sanitize_text_field',
			'auth_callback'     => 'acme_meta_auth',
			'show_in_rest'      => true,
		)
	);

	register_post_meta(
		'post',
		'acme_featured',
		array(
			'type'              => 'boolean',
			'single'            => true,
			'description'       => __( 'Pin this post to the top of archives.', 'acme' ),
			'default'           => false,
			'sanitize_callback' => 'rest_sanitize_boolean',
			'auth_callback'     => 'acme_meta_auth',
			'show_in_rest'      => true,
		)
	);
}
add_action( 'init', 'acme_register_meta' );

/**
 * Read acme_reading_time.
 *
 * @param int $post_id Post ID.
 * @return mixed
 */
function acme_get_reading_time( $post_id = 0 ) {
	$post_id = $post_id ? $post_id : get_the_ID();

	return get_post_meta( $post_id, 'acme_reading_time', true );
}

/**
 * Read acme_subtitle.
 *
 * @param int $post_id Post ID.
 * @return mixed
 */
function acme_get_subtitle( $post_id = 0 ) {
	$post_id = $post_id ? $post_id : get_the_ID();

	return get_post_meta( $post_id, 'acme_subtitle', true );
}

/**
 * Read acme_featured.
 *
 * @param int $post_id Post ID.
 * @return mixed
 */
function acme_get_featured( $post_id = 0 ) {
	$post_id = $post_id ? $post_id : get_the_ID();

	return get_post_meta( $post_id, 'acme_featured', true );
}

/*
 * uninstall.php — remove the meta when the plugin is deleted.
 *
 * defined( 'WP_UNINSTALL_PLUGIN' ) || exit;
 * delete_post_meta_by_key( 'acme_reading_time' );
 * delete_post_meta_by_key( 'acme_subtitle' );
 * delete_post_meta_by_key( 'acme_featured' );
 */