How to Create Custom Meta Boxes & Custom Fields in WordPress?

Anh Tran
Meta Box
Published in
8 min readJul 19, 2018

The default custom fields functionality in WordPress is to help end-users customize their websites fast and easily. But, it is limited to only text fields and thus, is not enough in most cases. In this post, we will learn how to take control of custom fields by creating our own new field types.

Requirements:

Before going into the details, it should be mentioned that you need to have some basic knowledge about:

  1. PHP and HTML
  2. How to make a simple WordPress plugin

In WordPress, there are no functions to add any user interface for custom fields directly. All functions related to custom fields are made via an API named meta box. So, let’s talk about the meta box before going into the details of creating new custom fields.

What is meta box?

Back to the first post of this series, we know the definition of custom fields is:

Custom fields is a feature that helps us create forms and fields to interact with metadata.

So that, in term of the user interface, custom fields are the form fields which allow users to fill data.

In the page “edit post” of WordPress, you’ll see the areas contain additional information about the post such as Publish box, Format box, and Categories box. That information is grouped into boxes called “meta boxes”, which means boxes that contain metadata. This is the origin of our plugin’s name, Meta Box. However, the term “meta box” here refers to the above boxes, not our plugin.

Meta box in the edit post screen
Meta boxes in the edit post screen

In the previous post, the meta box “Custom Fields” is used to add custom fields of the text type. In the next section, let’s create a meta box that has some different field types. To do that, we need to create a small plugin.

Create a simple custom field plugin

Creating a plugin is the recommended way to add functionality to WordPress. Let’s create a simple plugin named “Hello Custom Fields”. Follow these steps:

  1. Create a folder hello-custom-fields inside wp-content/plugins.
  2. Inside that folder, create a file hello-custom-fields.php with content below:
<?php
/**
* Plugin Name: Hello Custom Field
* Plugin URI: https://metabox.io
* Description: A simple plugin for custom fields.
* Version: 1.0
* Author: Meta Box
* Author URI: https://metabox.io
* License: GPL2
*/

You can read more detail about how to make a plugin here.

For the demonstration purpose, we will make a plugin that allows users to fill in the information of a book. The fields we need are:

  1. Author: a text field
  2. Publish year: a date field
  3. Price: a number field

Things we need to do in next:

  1. Create a meta box
  2. Add custom fields to that meta box
  3. Save the values of custom fields
  4. Display the value of each custom field in the front end

Here we go!

Create a meta box

WordPress provides a function add_meta_box to add meta box in whatever page we want. This function has the following syntax:

add_meta_box( $id, $title, $callback, $screen, $context, $priority, $callback_args)

Where:

Name Description $id Meta box ID $title Title of the meta box. $callback The function that fills the box with the desired content. The function should echo its output. $screen The screen or screens on which to show the box (such as a post type, link, or comment). $context The context within the screen where the boxes should display. Post edit screen contexts include normal, side, and advanced. Default value: advanced. $priority The priority within the context where the boxes should show (high, low). Default value: high. $callback_args Data that should be set as the $args property of the box array (which is the second parameter passed to your callback). Default value: null.

We’ll create a meta box with title “Hello Custom Fields” in the edit/create posts screen. Open the file hello-custom-fields.php and add the following snippet:

/**
* Register meta boxes.
*/
function hcf_register_meta_boxes() {
add_meta_box( 'hcf-1', __( 'Hello Custom Field', 'hcf' ), 'hcf_display_callback', 'post' );
}
add_action( 'add_meta_boxes', 'hcf_register_meta_boxes' );

/**
* Meta box display callback.
*
* @param WP_Post $post Current post object.
*/
function hcf_display_callback( $post ) {
echo "Hello Custom Field";
}

Anything echoed in the function hcf_display_callback will be displayed.

Display of function hcf_display_callback in custom fields
Result of function hcf_display_callback in custom fields

Currently, this function displays only a simple text paragraph. In the next section, we will display some inputs for users to enter values for books.

Add custom fields into a meta box

To add custom fields into a meta box, we need to modify the callback function to output form inputs. To shorten the code, let’s create a file form.php that contains the code of the form. Here is the snippet:

/**
* Meta box display callback.
*
* @param WP_Post $post Current post object.
*/
function hcf_display_callback( $post ) {
include plugin_dir_path( __FILE__ ) . './form.php';
}

Content of the file form.php as below:

<div class="hcf_box">
<style scoped>
.hcf_box{
display: grid;
grid-template-columns: max-content 1fr;
grid-row-gap: 10px;
grid-column-gap: 20px;
}
.hcf_field{
display: contents;
}
</style>
<p class="meta-options hcf_field">
<label for="hcf_author">Author</label>
<input id="hcf_author" type="text" name="hcf_author">
</p>
<p class="meta-options hcf_field">
<label for="hcf_published_date">Published Date</label>
<input id="hcf_published_date" type="date" name="hcf_published_date">
</p>
<p class="meta-options hcf_field">
<label for="hcf_price">Price</label>
<input id="hcf_price" type="number" name="hcf_price">
</p>
</div>

You can separate the style into an individual file. But, it is not necessary in this case because we are making a small example only and the code is simple.

The result will be like this:

Add custom fields into meta box
Add custom fields into a meta box

Unlike the default functionality of WordPress which supports only text fields, a custom form code allows you to use whatever type of fields you want. In the above screenshot, we use a date field which allows users to pick any date without entering manually.

This ability helps users fill data easier, reduce the mistakes, and help you validate the data (if needed).

Save the custom fields

We had the form for users to fill data, but WordPress does not save it automatically. We must save it ourselves.

In order to save custom fields when users save or update a post, we need to hook to action save_post. save_post is called after the post is saved. To save the custom fields, we'll use the function update_post_meta. Put the following code into the plugin file:

/**
* Save meta box content.
*
* @param int $post_id Post ID
*/
function hcf_save_meta_box( $post_id ) {
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
if ( $parent_id = wp_is_post_revision( $post_id ) ) {
$post_id = $parent_id;
}
$fields = [
'hcf_author',
'hcf_published_date',
'hcf_price',
];
foreach ( $fields as $field ) {
if ( array_key_exists( $field, $_POST ) ) {
update_post_meta( $post_id, $field, sanitize_text_field( $_POST[$field] ) );
}
}
}
add_action( 'save_post', 'hcf_save_meta_box' );

Now, try to fill data in meta box and save the post. After reloading the page, you will not see any value which you put into the fields. Don’t worry! The data have been saved into the database already.

Let’s take a look at the code of the form once again! Fields are missing attribute value which shows the value of the fields. So, we have to get the value of the fields, then output it to attribute value:

<div class="hcf_box">
<style scoped>
.hcf_box{
display: grid;
grid-template-columns: max-content 1fr;
grid-row-gap: 10px;
grid-column-gap: 20px;
}
.hcf_field{
display: contents;
}
</style>
<p class="meta-options hcf_field">
<label for="hcf_author">Author</label>
<input id="hcf_author"
type="text"
name="hcf_author"
value="<?php echo esc_attr( get_post_meta( get_the_ID(), 'hcf_author', true ) ); ?>">
</p>
<p class="meta-options hcf_field">
<label for="hcf_published_date">Published Date</label>
<input id="hcf_published_date"
type="date"
name="hcf_published_date"
value="<?php echo esc_attr( get_post_meta( get_the_ID(), 'hcf_published_date', true ) ); ?>">
</p>
<p class="meta-options hcf_field">
<label for="hcf_price">Price</label>
<input id="hcf_price"
type="number"
name="hcf_price"
value="<?php echo esc_attr( get_post_meta( get_the_ID(), 'hcf_price', true ) ); ?>">
</p>
</div>

Then, the result is:

Fill value into custom fields by values of metadata
Display values of custom fields after saving

We have done creating a meta box, adding custom fields to edit screen, save the custom fields values. That’s all for the backend. And our simple plugin is done!

Now let’s get the custom fields value and display them in the frontend. We’ll need to modify our theme’s files a little bit.

Get and display custom fields in the frontend

To get the custom fields values, all we need to do is using the function get_post_meta. We have talked about this in the previous post. The code doesn't change too much:

<ul>
<li><strong>Author: </strong><?php echo esc_attr( get_post_meta( get_the_ID(), 'hcf_author', true ) ); ?></li>
<li><strong>Published Date: </strong><?php echo esc_attr( get_post_meta( get_the_ID(), 'hcf_published_date', true ) ); ?></li>
<li><strong>Price: </strong><?php echo esc_attr( get_post_meta( get_the_ID(), 'hcf_price', true ) ); ?></li>
</ul>

Get custom fields values outside the loop

The function get_post_meta requires a mandatory parameter for post ID. If you want to get custom field data from any post outside the loop, you need to know its ID. There are many ways to get it.

#1: Hardcode the post ID

There are many ways to hardcode. You may use post ID directly in the function get_post_meta as below:

get_post_meta( 12, 'hcf_author', true );

Or, define it in a file of that function:

// In the wp-config.php file 
define( MY_POST_ID, 12 );

// In the theme's file
echo get_post_meta( MY_POST_ID, 'hcf_author', true);

However, the hardcode is not encouraged. If you make some queries to get posts, then you can use the ID of the queried posts and pass it to the get_post_meta function.

#2: Get the post ID from queries

The following code demonstrates getting custom field’s value from a post in a custom query:

$the_slug = 'my_slug';
$args = array(
'name' => $the_slug,
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => 1,
);
$my_posts = get_posts( $args );
$my_post = current( $my_posts );
if ( $my_post ) {
echo get_post_meta( $my_post->ID, 'hcf_author', true );
}

Conclusion

Creating your own custom fields requires some codes. But it gives you the full power to decide using which field type to use to fit your needs. Although, it also means that you are responsible for handling the the data.

You can create any field type you want, even the most complicated field types such as gallery or repeater field. It depends only on your coding skill and your imagination.

Back to the meaning of the custom fields, it is the implementation of the metadata architecture. Custom fields give us more information about objects (posts). However, until now, we only use it to store the data and display the data. However, one of the most popular applications of the custom fields is getting posts based on their value. Let’s talk about that later in this series.

Originally published at Meta Box.

--

--

Anh Tran
Meta Box

A WordPress and web developer. Lead developer of Meta Box plugin for WordPress and premium theme shop GretaThemes.