WordPress Custom Post Type Meta Box with Form Validation

So I'm going to cover a lot in a little time in this tutorial so pay close attention and you'll learn fast I hope.

add_car

What You'll Learn

  • How to create a simple WordPress plugin
  • How to create a custom post type in WordPress
  • How to add custom fields to a custom post type
  • How to add meta boxes to wp-admin
  • How to save custom post type's custom fields
  • How to handle form validation for custom meta boxes
  • How to display errors in wp-admin

So while it might seem like a lot to cover, I will demonstrate all of the above points with a simple WordPress plugin that adds a custom post type to WordPress and validates the user's input.

Here are the steps you'll follow:

  1. Start a new plugin
  2. Add a new custom post type
  3. Add meta boxes to a custom post type
  4. Add WordPress Error Handler Functions
  5. Write PHP Function to Save Custom Fields Data Meta Boxes

Step One - Start a new plugin

Create a folder on your desktop, pick a name for your plugin and name the folder accordingly. Lets say for the purpose of making this tutorial, we'll name our plugin "Cars" so we created a folder named "cars" on our desktop. Then add a php file named cars.php and make enter the proper comments at the top of the cars.php file so WordPress will recognize your new plugin. Here's how I did it:

<?php
/**
 * Plugin Name: Cars
 * Plugin URI: http://jafty.com/blog/crash-course-on-wordpress-plugin-development/
 * Description: A custom Car plugin developed for WordPress car websites.
 * Version: 0.0.1
 * Author: Ian L. of Jafty.com
 * Author URI: http://jafty.com
 * License: GPL2
 */

?>

Feel free to change the name , Plugin URI, Description, etc to fit your desires.

Step Two - Add a Custom Post Type

Next we need to add code to cars.php that will create a new Custom Post Type or CPT in wordpress. Here's example code to create the cars CPT:

//Add cars Custom Post Type:
add_action('init', 'create_cars_cpt');
function create_cars_cpt() {
    $labels = array(    
      'name' => _x( 'cars', 'cars' ),
      'singular_name' => _x( 'car', 'cars' ),
      'add_new' => _x( 'Add New car', 'cars' ),
      'add_new_item' => _x( 'Add New car', 'cars' ),
      'edit_item' => _x( 'Edit car', 'cars' ),
      'new_item' => _x( 'New car', 'cars' ),
      'view_item' => _x( 'View car', 'cars' ),
      'search_items' => _x( 'Search cars', 'cars' ),
      'not_found' => _x( 'No cars found', 'cars' ),
      'not_found_in_trash' => _x( 'No cars found in Trash', 'cars' ),
      'parent_item_colon' => _x( 'Parent car:', 'cars' ),
      'menu_name' => _x( 'cars', 'cars' ),
   );
   
   
 $args = array(
      'labels' => $labels,
      'hierarchical' => false,
      'description' => 'cars',
      'supports' => array( 'title', 'author' ),//author adds the author metabox to cars CPT add car/edit car screens.
      'public' => true,
      'show_ui' => true,
      'show_in_menu' => true,
      'show_in_nav_menus' => true,
      'publicly_queryable' => true,
      'exclude_from_search' => false,
      'has_archive' => true,
      'query_var' => true,
      'can_export' => true,
      'rewrite' => array('slug' => 'car'),
      'map_meta_cap'  => true,
   );

    register_post_type( 'cars', $args );
    //flush_rewrite_rules();
}//end create_cars_cpt function

Simply add the above code in green to your cars.php file after the comment area but before then closing PHP tag and save the file.

Step Three - Add simple Meta Box to Our Plugin

Here is my code for reference which you may copy, paste and change as needed:

//Add the Cars Meta Boxes:
add_action( 'add_meta_boxes', 'add_cars_metaboxes' );
function add_cars_metaboxes() {
add_meta_box('create_car_metabox', 'Car Information', 'create_car_metabox', 'cars', 'normal', 'high');
}
      
//############################## Function to create the meta box: ########################
function create_car_metabox($p='') {
global $post;
// Noncename needed to verify where the data originated
echo '<input type="hidden" name="eventmeta_noncename" id="eventmeta_noncename" value="' .
wp_create_nonce(plugin_basename(__FILE__)) . '" />';

$car_year = get_post_meta($p, '_car_year', true);
$car_make = get_post_meta($p, '_car_make_time', true);
$car_model = get_post_meta($p, '_car_model_time', true);

if(isset($post->ID)){
//get post meta for car:
$car_year = get_post_meta($post->ID, '_car_year', true);
$car_make = get_post_meta($post->ID, '_car_make_time', true);
$car_model = get_post_meta($post->ID, '_car_model_time', true);
}//end if post ID is set

//add HTML for meta box form fields:
?>
<div style="float:left">
<span class='field-head'>Car Year:</span> <select name="car_year">
<option value="none">Select Year</option>
<option value="1990"<?php if($car_year=="1990")echo " selected";?>>1990</option>
<option value="1991"<?php if($car_year=="1991")echo " selected";?>>1991</option>
<option value="1992"<?php if($car_year=="1992")echo " selected";?>>1992</option>
</select>
</div>

<div style="float:left">
<span class='field-head'>Car Make:</span> <select name="car_make">
<option value="none">Select Make</option>
<option value="Ford"<?php if($car_make=="Ford")echo " selected";?>>Ford</option>
<option value="Chevy"<?php if($car_make=="Chevy")echo " selected";?>>Chevy</option>
<option value="Dodge"<?php if($car_make=="Dodge")echo " selected";?>>Dodge</option>
</select>
</div>

<div style="float:left">
<span class='field-head'>Car Model:</span> <select name="car_model">
<option value="none">Select Model</option>
<option value="1990"<?php if($car_model=="1990")echo " selected";?>>1990</option>
<option value="1991"<?php if($car_model=="1991")echo " selected";?>>1991</option>
<option value="1992"<?php if($car_model=="1992")echo " selected";?>>1992</option>
</select>
</div>
<?php

}//end create_car_metabox function to create car tabs

Paste the above code in your cars.php file right after the last line of PHP code but before the closing PHP tag.

Step Four - Add Error Handling Functions to Your Plugin:

Now we need a couple quick functions to handle errors later on, so copy and paste the following code into your cars.php file next just after the last code you added from step three above:

//Next we need two simple error handling functions:
//Error handling function for use with save_car_data function below it:
add_action('admin_notices', 'handle_car_errors');
/**
 * Writes an error message to the screen if error is thrown in save_car_data function
 *
 */
function handle_car_errors() {
  //If there are no errors, then exit the function
  if(!( $errors = get_transient('settings_errors'))) {
    return;
  }
  //Otherwise, build the list of errors that exist in the settings errors
  $message = '<div id="acme-message" class="error below-h2"><p><ul>';
  foreach($errors as $error) {
    $message .= '<li>' . $error['message'] . '</li>';
  }
  $message .= '</ul></p></div><!-- #error -->';
  //Write error messages to the screen
  echo $message;
  //Clear and the transient and unhook any other notices so we don't see duplicate messages
  delete_transient('settings_errors');
  remove_action('admin_notices', 'handle_car_errors');
}

function car_error($slug,$err){
    add_settings_error(
        $slug,
        $slug,
        $err,
        'error'
    );
    set_transient('settings_errors', get_settings_errors(), 30);
}//end car_error function by Ian L. of Jafty.com

Step Five - Save Meta Box Data in WordPress

Now that we have our error handling functions ready, we can write in our function to save the data. You can copy and paste my save_car_data function and it's action hook as follows:

//############### SAVE ALL ABOVE METADATA FROM META BOXES HERE: ##################
//hook to save the meta box data:
//add_action('save_post', 'save_touchpoint_data');
add_action('save_post_cars', 'save_car_data');
    
function save_car_data($post_id) {
    //get the car post's title title and verify it first:
    $ti = get_the_title($post_id);
    //if the title is blank, throw an error:
    if($ti=='')car_error('title_missing','Oops! You forgot to enter a title. Please enter a valid car title and click the update button.');

    //save the car's year:
    //first make sure they picked a year:
    $y = $_POST['car_year'];
    if($y == 'none'){
        car_error('missing_car_year','Opps! You have not selected a year for the car. Please select a year and click the update button to save it afterwards.');
    }else{
    update_post_meta($post_id, '_car_year', strip_tags($y));
    }
    
    //save the car's make:
    //first make sure they picked a make:
    $y = $_POST['car_make'];
    if($y == 'none'){
        car_error('missing_car_make','Opps! You have not selected a make for the car. Please select a make and click the update button to save it afterwards.');
    }else{
    update_post_meta($post_id, '_car_make', strip_tags($y));
    }
    
    //save the car's model:
    //first make sure they picked a model:
    $y = $_POST['car_model'];
    if($y == 'none'){
        car_error('missing_car_model','Opps! You have not selected a model for the car. Please select a model and click the update button to save it afterwards.');
    }else{
    update_post_meta($post_id, '_car_model', strip_tags($y));
    }
}//end save_car_data function

That's all there is to it! Copy and paste the above code into your cars.php file just before the closing PHP tag and save the file, then upload the entire cars folder to your site's plugins directory and navigate to wp-admin and click on "plugins" then find your new plugin and click "activate" to activate it and you will see the new custom post type, "Cars" appear in the main wp-admin nav that runs down the left side of the page.

Screen Shots:

Here is what it will look like if you just try to click on "Publish" when adding a new car without entering any values into the add new car page at all:

errors

Below is what the add new Car screen looks like:

add_car

Summary:

There you have it! A simple plugin with everything you need to get you started creating your own custom post types in WordPress that include custom fields, meta boxes and even error handling code! A WordPress beginner's dream! Good Luck with your next theme or plugin!

Leave a Reply

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