HTML
Introduction To Custom Post Type In WordPress 3 – Part 2
November 24, 2010
0

In this part of the turorial, we will explore how to extend WordPress forms to show new fields in Custom Post Types that we created in the previous part of the tutorial. The previous part of this tutorial can be read here:
https://www.permadi.com/blog/2010/11/introduction-to-custom-post-types-in-wordpress-3-part-1/.

This part of the tutorial will show you how to create custom form for the Custom Post Types, such as shown below:

Adding Custom Form Fields

As mentioned in the previous tutorial, the code that is explained here can be added into functions.php of your theme, however, we are going to use a module because this allows for more flexibility (if you change theme, then you don’t have to copy the code to the new theme’s functions.php).

Let’s call the function in the module file we created in the previous tutorial. Open the module file.

To add custom fields into the form, we will use add_meta_box() function.   See http://codex.wordpress.org/Function_Reference/add_meta_box for more information.

add_meta_box("book-form-meta-box", "Book Info",
   "init_permadi_com_book_type_metaboxes", "books");

Some notes:

  • book-form-meta-box is the id of the meta-box.
  • Book Info is the title of the meta-box.
  • init_permadi_com_book_type_metaboxes is name of the function that constructs the meta-box (you will see this function soon).
  • books is the custom post type that will have the meta-box (this is telling Wordpess: “only add the metabox if the post-type is books“).

Below again is a complete version of our example plug-in (permadi-custom-post-types.phpsee the previous tutorial if neccessary).

<?php
/*
Plugin Name: Permadi Custom Type
Description: My example bare-bone plugin.
Author: F. Permadi Version: 1.0
*/

function create_permadi_com_post_type()
{
	register_post_type('books',
		array(
			'labels' => array(
			'name' => __('Books'),
			'singular_name' => __('Book'),
		 ),
		'show_ui' => true,
		'capability_type' => 'post',
		'public' => true,
		)
	);

	register_post_type('tapes',
		array(
			'labels' => array(
			'name' => __('Tapes'),
			'singular_name' => __('Tape'),
		 ),
		'show_ui' => true,
		'capability_type' => 'post',
		'public' => true,
		)
	);
}

add_action('init', 'create_permadi_com_post_type');
?>

Add these code below to the file (after the last line but before the closing php tag):

function create_permadi_com_metaboxes()
{
	add_meta_box("book-form-meta-box", "Book Info",
		"init_permadi_com_book_type_metaboxes", "books");
}

function init_permadi_com_book_type_metaboxes()
{
	global $post;

	// Read existing data (if any)
	$bookCustomData=get_post_custom($post->ID);
	//var_dump($bookCustomData);
	?>
		<label>Author</label>
		<input name="author" value="<?php echo $bookCustomData['author'][0]; ?>">

		<label>Price</label>
		<input name="price" value="<?php echo $bookCustomData['price'][0]; ?>">
	<?php
}

add_action('admin_init', 'create_permadi_com_metaboxes');
?>

Pay attention to the init_permadi_com_book_type_metaboxes() function. This is where I added two custom form-fields, named author and price.

Note:

  • The line add_action(‘admin_init’, ‘create_permadi_com_metaboxes’) tells WordPress to call create_permadi_com_metaboxes() during admin_initsequence (when editing a post).
  • For clarity, I am adding each field (author, price) manually, but you can do this more efficient by using foreach and storing the custom fields in arrays.
  • The line get_post_custom($post->ID); currently does nothing, but later on this will be used to pull data from a saved post (so that if you re-edit a post, you’ll see the previously entered values).

 

To test this new form, login to WordPress with the plug-in, then add a new Book-type post.

After the form is open, scroll to the bottom and you should see the so called meta-box (ie: form box) for our books Custom Post Type.

Note that the position of this form can be controlled in add_meta_box().  See the documentation of add_meta_box() here http://codex.wordpress.org/Function_Reference/add_meta_box, the $context parameter controls the position of the box (you can not position the exact location but you can set it to appear on the side or below) .

Saving The Custom Form Fields Data

Use update_post_meta() (http://codex.wordpress.org/Function_Reference/update_post_meta) to save the custom form data, like below:

function save_permadi_com_metaboxes($postId, $post=null)
{
  if ($post->post_type=="books")
  {
  update_post_meta($postId, "author", $_POST['author']);
  update_post_meta($postId, "price", $_POST['price']);
  }
}

add_action('wp_insert_post', 'save_permadi_com_metaboxes', 10, 2);

Some note:

  • As usual, we need to hook this function so that WordPress knows that it should call it when saving a post. This is done with:
    add_action(‘wp_insert_post’, ‘save_permadi_com_metaboxes’, 10, 2). 10 is the priority value (I suggest not to change this), and 2 is the number of arguments in the save_permadi_com_metaboxes() function.

 

  • Notice that the call to  update_post_meta() will replace existing value for the key if it already exists.

    More Custom Fields

    The code below demonstrates using check-box, combo-box (pull-down list) and radio-boxes. The check-box input is tricky because you need to create a separate property name for each check box. This can be automated with a function but I am showing it in this state for clarity. This code also contains the full module for this example.

     <?php
     /*
     Plugin Name: Permadi Custom Type
     Description: My example bare-bone plugin.
     Author: F. Permadi Version: 1.0
     */
     function create_permadi_com_post_type()
     {
       register_post_type('books',
         array(
           'labels' => array(
             'name' => __('Books'),
             'singular_name' => __('Book'),
           ),
           'show_ui' => true,
           'capability_type' => 'post',
           'public' => true,
           )
         );
       register_post_type('tapes',
         array(
          'labels' => array(
             'name' => __('Tapes'),
             'singular_name' => __('Tape'),
            ),
           'show_ui' => true,
           'capability_type' => 'post',
           'public' => true,
         )
       );
     }
    
     function create_permadi_com_metaboxes()
     {
       add_meta_box("book-form-meta-box", "Book Info", "init_permadi_com_book_type_metaboxes", "books");
     }
    
     function save_permadi_com_metaboxes($postId, $post=null)
     {
       if ($post->post_type=="books")
       {
         // You should call update_post_meta() first so that if there's any previous data, it will be updated.
         // If you keep calling add_post_meta() without checking, the data will be appended. This is why
         // you see the call to get_post_custom() returns array of arrays.
         update_post_meta($postId, "author", $_POST['author']);
         update_post_meta($postId, "number-of-pages", $_POST['number-of-pages']);
         update_post_meta($postId, "price", $_POST['price']);
         update_post_meta($postId, "genre", $_POST['genre']);
         update_post_meta($postId, "image-filename", $_POST['image-filename']);
         update_post_meta($postId, "language1", $_POST['language1']);
         update_post_meta($postId, "language2", $_POST['language2']);
         update_post_meta($postId, "language3", $_POST['language3']);
         update_post_meta($postId, "free-shipping", $_POST['free-shipping']);
       }
     }
    
     function init_permadi_com_book_type_metaboxes()
     {
       global $post;
       // Read existing data (if any)
       $bookCustomData=get_post_custom($post->ID);
       var_dump($bookCustomData);
    ?>
       <table>
       <tr>
         <td width="200">
           <label>Author</label>
         </td>
         <td>
           <input name="author" value="<?php echo $bookCustomData['author'][0]; ?>">
         </td>
       </tr>
       <tr>
         <td>
           <label>Price</label>
         </td>
         <td>
           <input name="price" value="<?php echo $bookCustomData['price'][0]; ?>">
         </td>
       </tr>
       <tr>
         <td>
           <label>Number Of Pages</label>
         </td>
         <td>
           <input name="number-of-pages" value="<?php echo $bookCustomData['number-of-pages'][0]; ?>">
         </td>
       </tr>
       <tr>
         <td>
           <label>Genre</label>
         </td>
         <td>
           <select name="genre">
             <option value="mystery"
               <?php if ($bookCustomData['genre'][0]=="mystery") echo "selected"; ?>>
                  Mystery
             </option>
             <option value="science-fiction"
               <?php if ($bookCustomData['genre'][0]=="science-fiction") echo "selected"; ?>>
                 Science Fiction
             </option>
             <option value="comic"
               <?php if ($bookCustomData['genre'][0]=="comic") echo "selected"; ?>>
                  Comic
             </option>
             <option value="sport" 
               <?php if ($bookCustomData['genre'][0]=="sport") echo "selected"; ?>>
               Sport
             </option>
           </select>
         </td>
       </tr>
       <tr>
         <td>
           <label>Free Shipping</label>
         </td>
         <td>
           <input type="radio" name="free-shipping" value="yes"
             <?php if ($bookCustomData['free-shipping'][0]=="yes") echo "checked"; ?>>
               Yes
           </input>
           <input type="radio" name="free-shipping" value="no"
             <?php if ($bookCustomData['free-shipping'][0]=="no") echo "checked"; ?>>No
           </input>
           <input type="radio" name="free-shipping" value="unknown"
             <?php if ($bookCustomData['free-shipping'][0]=="unknown") echo "checked"; ?>>Unknown
           </input>
         </td>
       </tr>
       <tr>
         <td>
           <label>Language</label>
         </td>
         <td>
            <input type="checkbox" name="language1" value="yes"
             <?php if ($bookCustomData['language1'][0]=="yes") echo "checked"; ?>>
              English
            </input>
            <input type="checkbox" name="language2" value="yes"
              <?php if ($bookCustomData['language2'][0]=="yes") echo "checked"; ?>>Chinese
           </input>
           <input type="checkbox" name="language3" value="yes"
             <?php if ($bookCustomData['language3'][0]=="yes") echo "checked"; ?>>Spanish
           </input>
         </select>
     </td>
     </tr><tr>
     <td>
     <label>Image Filename</label>
     </td>
     <td>
     <input size=100 name="image-filename" value="<?php echo $bookCustomData['image-filename'][0]; ?>">
     </td>
     </tr></pre>
    <pre></table>
     <?php
     }</pre>
    <pre>add_action('init', 'create_permadi_com_post_type');
     add_action('admin_init', 'create_permadi_com_metaboxes');
     add_action('wp_insert_post', 'save_permadi_com_metaboxes', 10, 2);
     ?></pre>
    

    Test the example and it should look like this:

    So far we have been able to add and save the metabox data, but we have’t show how to display them. This will be on the next tutorial. PS: If you find this tutorial useful, click the Facebook like button to encourage me to write the next tutorial.