Storing Variable Post Meta Data In WordPress Without Plugins
Why Store Custom Post Meta
WordPress stores built-in information about posts, pages, and custom post types like titles, content, dates, authors, tags, categories, featured images, etc. However, you may need to store additional custom data for advanced functionality.
For example, if you are building a directory website, you need to store extra information like addresses, phone numbers, hours of operation. Or an e-commerce site needs to save product prices, stock levels, dimensions, etc.
By leveraging the update_post_meta()
and get_post_meta()
functions you can programmatically attach custom metadata to posts, pages, and custom post types without relying on plugins.
Benefits of Custom Post Meta Data
- Extend built-in data to suit specialized requirements
- Attach unlimited additional information to WordPress posts
- Build custom input forms to manage the data
- Enables advanced custom applications and functionality
- Avoid bloat from unnecessary plugins
Using the update_post_meta() Function
The update_post_meta()
function allows you to programmatically add custom data to any post type object. It automatically handles validation, sanitization, and adding the data to the post meta database table.
Basic Usage and Syntax
update_post_meta( $post_id, $meta_key, $meta_value, $unique );
To use it, you simply pass the post ID you want to update, the custom data key, the actual data value, and whether it should be unique or not.
For example:
update_post_meta( 123, 'price', 19.99 ); update_post_meta( 155, 'stock_count', 10 );
This would add a “price” meta field with a value of “19.99” to post ID 123, and a “stock_count” field with a value of “10” to post ID 155.
Understanding the Arguments
Let’s break down what each argument does:
$post_id
– Integer ID for the post you want to update$meta_key
– Custom text string to identify the data$meta_value
– Actual data in string, array, object, or other format$unique
– Optional boolean to only allow one value for a key
Both the meta key and values can use text strings, numbers, array, serialized objects, or other data types.
You need to uniquely identify each custom data value with the meta key, which is why using descriptive names like “price” or “dimensions” makes it easy to understand.
Reading Post Meta with get_post_meta()
Once you have used update_post_meta() to attach metadata, you can then retrieve it using:
get_post_meta( $post_id, $meta_key, $single );
This function fetches the stored data based on the post ID and key. You can choose whether to get just a single value or return an array of all data under that key.
Querying Metadata
Call get_post_meta() whenever you need to retrieve the posted information in themes or plugins.
For example, on a single post page you may want to display the custom price and stock data.
$price = get_post_meta( get_the_ID(), 'price', true ); $stock = get_post_meta( get_the_ID(), 'stock_count', true ); echo $price . ' - only ' . $stock;
By passing true as the 3rd argument, it will return a single string or number value for usage in PHP.
Usage Examples
A few examples to demonstrate get_post_meta() in action:
// Get all meta values for key $values = get_post_meta( 34, 'color', false ); // Get first value for a key $price = get_post_meta( 67, 'price', true ); // Number values $rooms = get_post_meta( 841, 'rooms', true ); // Arrays from stored JSON $tags = get_post_meta( 302, 'related_tags', true ); $tags = json_decode( $tags );
This allows easy access to retrieve and display any kind of metadata in WordPress themes and plugins.
Setting Up Custom Post Meta Input Fields
Manually calling update/get_post_meta() works great in code, but for content editors to add data you need custom input forms on the post editor.
WordPress provides filter hooks to render additional fields alongside built-in title, content editors etc. No special plugins needed.
Adding Input Fields
The add_meta_box()
hook allows defining new meta boxes:
/** * Register price meta box */ function add_price_metabox() { add_meta_box( 'price_data', __( 'Pricing', 'mytextdomain' ), 'render_pricing_box', 'post' ); } add_action( 'add_meta_boxes', 'add_price_metabox' );
Then render fields inside that meta box:
/** * Output price fields */ function render_pricing_box() { // Nonce for verification wp_nonce_field( 'save_price_data', 'price_nonce' ); // Output form fields echo ''; echo ''; }
This provides a simple price text input box that content editors can populate with pricing data.
Saving Submitted Meta Data
When the post form is submitted, hook in to intercept and save:
/** * Save price data */ function save_price_fields( $post_id ) { // Verify nonce if ( !isset( $_POST['price_nonce'] ) || !wp_verify_nonce( $_POST['price_nonce'], 'save_price_data' ) ) { return; } // Sanitize user input $price = sanitize_text_field( $_POST['price'] ); // Update post meta update_post_meta( $post_id, 'price', $price ); } add_action( 'save_post_post', 'save_price_fields' );
That validates the nonce, sanitizes data, and updates post meta all in one function hooked on save_post. The price will now persist in post meta automatically!
Displaying Variable Post Meta in Templates
In addition to saving custom post meta data, you also need to output it publicly on the front end. Typically this is done in single post templates, archives, or custom Page templates.
Outputting Values in PHP
Use the familiar get_post_meta() to first retrieve the value. For example on single posts:
$price = get_post_meta( get_the_ID(), 'price', true );
Then echo the variable in HTML markup as needed:
<div class="price"> <span>Price: </span> <?php echo $price; ?> </div>
For arrays, loops through each element.
Sanitize and Escape
Since editors can modify custom meta values, always sanitize:
$rooms = sanitize_text_field( get_post_meta( 34, 'rooms', true ) );
Escaping for spans HTML output:
$desc = esc_html( get_post_meta( 55, 'description', true ) ); echo "<span>$desc</span>";
Taking care to escape and sanitize between retrieval and output prevents issues from un-trusted text in metadata fields
Storing Arrays and Objects as Post Meta
So far we have looked at saving simple string and number values. For more complex data structures, the serialized post meta allows arrays, multi-dimensional arrays, and objects.
Serializing Arrays and Objects
Native post meta data types can only store simple values. For anything more complex, first serialize into a string representation.
For example arrays:
$data = array( 'color' => 'blue', 'sizes' => array( 'S', 'M', 'L' ) ); update_post_meta( 44, 'product_vars', serialize( $data ) );
And JSON encoded objects:
$extra = (object)[ 'author' => 'John Doe', 'format' => 'Kindle Edition' ]; $json = json_encode( $extra ); update_post_meta( 88, 'ebook_data', $json );
This takes arrays, objects and encodes them into a textual form the database can store. Retrieve them in the same way.
Unserializing Data
On retrieval, unserialize arrays and objects back to original structure:
$product_vars = unserialize( get_post_meta( 44, 'product_vars', true ) ); // Array access echo $product_vars['color']; // Loop sizes foreach( $product_vars['sizes'] as $size ) { echo $size . ','; }
For JSON:
$json = get_post_meta( 88, 'ebook_data', true ); $extra = json_decode( $json ); // Object access echo $extra->format;
Now all the original array keys, object properties etc are available again in
code for easy access.
Case Study: Building a Custom Fields Plugin
Leveraging WordPress hooks and post meta functions, we can build a plugin that adds user friendly post custom fields without extra bloat.
Example Plugin Code
Skeleton of custom meta plugin:
/** * Plugin Name: Custom Meta Manager **/ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly /** * Activate Plugin */ function activate_cf_manager() { // Plugin activation code } register_activation_hook( __FILE__, 'activate_cf_manager' ); /** * Deactivate Plugin */ function deactivate_cf_manager() { // Plugin deactivation code } register_deactivation_hook( __FILE__, 'deactivate_cf_manager' ); /** * Initialize Plugin */ function cf_manager_init() { // Register custom meta boxes add_action( 'add_meta_boxes', 'cf_manager_add_meta' ); // Save and sanitize data add_action( 'save_post', 'cf_manager_save' ); // Load admin assets add_action( 'admin_enqueue_scripts', 'cf_manager_enqueue' ); } add_action( 'plugins_loaded', 'cf_manager_init' );
That provides the basic plugin scaffolding to start defining custom meta fields.
Building Out Custom Fields
Some examples for adding new pieces:
// Register fields function cf_manager_add_meta() { add_meta_box( 'cf_pricing', __( 'Pricing' ), 'cf_pricing_fields', 'post', 'side' ); } // Output pricing fields function cf_pricing_fields() { // Nonce and inputs echo ''; echo ''; } // Save price function cf_manager_save( $post_id ) { if ( isset( $_POST['cf_price'] ) ) { update_post_meta( $post_id, 'cf_price', sanitize_text_field( $_POST['cf_price'] ) ); } }
Keep adding more boxes, hooks, fields, and save handlers to store all kinds of custom data no plugin required!