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!

Leave a Reply

Your email address will not be published. Required fields are marked *