When starting with a new technology (in this case WordPress) I like to give myself a simple little project to get to know the platform, the APIs and the supporting languages. Back when I was teaching, one of the exercises was to create a simple “Quote of the Day”.
The original code was a Perl CGI application that parsed a simple text file, seperated it into the sections to display, and formatted it so it would display inline on the home page. The only additional function was to randomly select one quote to display each time the page was refreshed.
After reviewing the basic docs, I decided to do the following:
- Create a custom post type for the quotes
- Update the header section to place it over the image
- Give the user the option to turn it off (and as a phase 2) the choice of types to display
Just a quick warning about the code that follows, I am known to continuously tinker, so what you see below is very unlikely to actually be the code on the site unless you are reading this the moment I post!
Creating a custom post type is actually very easy, and I assume there are likely plug-ins that allow you to do all of this in a clean admin panel. However, that would be defeat the purpose of learning the inner workings of WordPress, so time to roll up the sleeves and create my QOTD php function file. Here is the code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | // The Quote post type add_action('init', 'qotd_post_type'); function qotd_post_type(){ register_post_type('qotd' ,array('labels' => array( 'name' => __( 'Quotes' ) ,'singular_name' => __( 'Quote' ) ,'add_new_item' => __('Add New Quote') ,'add_new' => _x('Add New', 'quote') ,'edit_item' => __('Edit Quote') ,'new_item' => __('New Quote') ,'all_items' => __('All Quotes') ,'view_item' => __('View Quotes') ,'search_items' => __('Search Quotes') ,'not_found' => __('No Quotes found') ,'not_found_in_trash' => __('No Quotes found in Trash') ,'menu_name' => 'Quotes' ) // end labels ,'public' => true ,'supports' => array('nothing') // see http://codex.wordpress.org/Function_Reference/post_type_supports ) // end options ); // end register post type } |
// The Quote post type add_action('init', 'qotd_post_type'); function qotd_post_type(){ register_post_type('qotd' ,array('labels' => array( 'name' => __( 'Quotes' ) ,'singular_name' => __( 'Quote' ) ,'add_new_item' => __('Add New Quote') ,'add_new' => _x('Add New', 'quote') ,'edit_item' => __('Edit Quote') ,'new_item' => __('New Quote') ,'all_items' => __('All Quotes') ,'view_item' => __('View Quotes') ,'search_items' => __('Search Quotes') ,'not_found' => __('No Quotes found') ,'not_found_in_trash' => __('No Quotes found in Trash') ,'menu_name' => 'Quotes' ) // end labels ,'public' => true ,'supports' => array('nothing') // see http://codex.wordpress.org/Function_Reference/post_type_supports ) // end options ); // end register post type }
The add_action()
places my function qotd_post_type()
in the “init” hook, which is just after the platform itself is loaded. All the function does is call the register_post_type()
method (our goal here) with my settings.
Okay, I have my post type. Now, I need a way to enter them. That is a little more complicated, and I had to go digging around the Codex for details. But it starts with creating the meta box:
1 2 3 4 | add_action('admin_init', 'qotd_admin'); function qotd_admin() { add_meta_box('quote_meta_box', 'Quote Details', 'display_quote_meta_box', 'qotd'); } |
add_action('admin_init', 'qotd_admin'); function qotd_admin() { add_meta_box('quote_meta_box', 'Quote Details', 'display_quote_meta_box', 'qotd'); }
This time I am hooking into the “admin_init”, since this is just for the admin page. The add_meta_box()
function has four parameters that I am using: the ID I chose to assign, the title of the meta box, the function (below) and finally the screen where this should be shown. In my case, I am using the ‘qotd’ (Quote post type) screen.
It’s going well, I just need to create the form so the admin can provide the quote, the person and the source. As an aside, I used a technique here that I really don’t like – breaking out of the php and providing “raw” HTML. When I repeated most of these steps for the FAQ code on this site, I actually print/echoed the code. I will leave that to personal preference.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | function display_quote_meta_box($qotd){ $title = $qotd->post_title; $quote = esc_html( get_post_meta($qotd->ID, 'quote', true)); $person = esc_html( get_post_meta($qotd->ID, 'person',true)); $source = esc_html( get_post_meta($qotd->ID, 'source', true)); ?> <table><tr> <td align="right">Quote ID:</td><td><?php echo $title ?></td> </tr> <tr> <td>Quote:</td> <td><input type="text" size="120" name="qotd_quote" value="<?php echo $quote; ?>" /></td> </tr> <tr> <td>Person:</td> <td><input type="text" size="80" name="qotd_person" value="<?php echo $person; ?>" /></td> </tr> <tr> <td>Source:</td> <td><input type="text" size="80" name="qotd_source" value="<?php echo $source; ?>" /></td> </tr> </table> <?php } |
function display_quote_meta_box($qotd){ $title = $qotd->post_title; $quote = esc_html( get_post_meta($qotd->ID, 'quote', true)); $person = esc_html( get_post_meta($qotd->ID, 'person',true)); $source = esc_html( get_post_meta($qotd->ID, 'source', true)); ?> <table><tr> <td align="right">Quote ID:</td><td><?php echo $title ?></td> </tr> <tr> <td>Quote:</td> <td><input type="text" size="120" name="qotd_quote" value="<?php echo $quote; ?>" /></td> </tr> <tr> <td>Person:</td> <td><input type="text" size="80" name="qotd_person" value="<?php echo $person; ?>" /></td> </tr> <tr> <td>Source:</td> <td><input type="text" size="80" name="qotd_source" value="<?php echo $source; ?>" /></td> </tr> </table> <?php }
You will notice that I did not give the admin the chance to provide a "title" for the quotes. A few reasons for that, but the primary one is that these quotes really don't have a title that would be displayed. An interesting thing I discovered is if you don't include the title in the list display, it is hard to actually edit it. So, I set it programmically:
1 2 3 4 5 6 7 8 9 | // Force title add_filter('title_save_pre', 'add_qotd_title'); function add_qotd_title($qotd_title){ if($_POST['post_type'] == 'qotd') { global $post; $qotd_title = sanitize_title('qotd-' . $post->ID); } return $qotd_title; } |
// Force title add_filter('title_save_pre', 'add_qotd_title'); function add_qotd_title($qotd_title){ if($_POST['post_type'] == 'qotd') { global $post; $qotd_title = sanitize_title('qotd-' . $post->ID); } return $qotd_title; }
I still need to save the other fields which is accomplished with the with the "save_post" hook like so:
1 2 3 4 5 6 7 8 9 10 11 12 13 | add_action('save_post', 'add_qotd_post', 10, 2); function add_qotd_post($qotd_id, $qotd){ if($qotd->post_type == 'qotd') { update_post_meta($qotd_id, 'post_title', sanitize_title('qotd-' . $qotd_id)); if ( isset( $_POST['qotd_quote'] ) && $_POST['qotd_quote'] != '' ) { update_post_meta( $qotd_id, 'quote', $_POST['qotd_quote'] ); } if ( isset( $_POST['qotd_person'] ) && $_POST['qotd_person'] != '' ) { update_post_meta( $qotd_id, 'person', $_POST['qotd_person'] ); } if ( isset( $_POST['qotd_source'] ) && $_POST['qotd_source'] != '' ) { update_post_meta( $qotd_id, 'source', $_POST['qotd_source'] ); } } } |
add_action('save_post', 'add_qotd_post', 10, 2); function add_qotd_post($qotd_id, $qotd){ if($qotd->post_type == 'qotd') { update_post_meta($qotd_id, 'post_title', sanitize_title('qotd-' . $qotd_id)); if ( isset( $_POST['qotd_quote'] ) && $_POST['qotd_quote'] != '' ) { update_post_meta( $qotd_id, 'quote', $_POST['qotd_quote'] ); } if ( isset( $_POST['qotd_person'] ) && $_POST['qotd_person'] != '' ) { update_post_meta( $qotd_id, 'person', $_POST['qotd_person'] ); } if ( isset( $_POST['qotd_source'] ) && $_POST['qotd_source'] != '' ) { update_post_meta( $qotd_id, 'source', $_POST['qotd_source'] ); } } }
There are a couple of new things happening in the code above. In addition to the "save_post" hook and my "add_qotd_post" function, there is a priority (set to 10 - the default) and the number of arguments I need to pass to the "save_post" function. In this case it is 2, which is the post ID and the post object itself. Now the obvious question is, how do you know? Unfortunately, the answer is "look it up" - in this case I used my IDE to check all the WordPress include files to find the function.
As for the code, the first step is to check that this really is a "quote" type post. Otherwise, we don't want to do anything with it. Next we are going to use the update_post_meta()
to add attributes to the post identified by the ID provided. The other interesting function, you will likely use a lot is the $_POST['field name']
which is how you access the form data.
Next time, I will cover the admin list display, sorting filters and tagging it. The third post in this series will be the all the pieces that went into the actual display, and how I built the option in the user profile. The fourth post, if I feel inspired to write it, is everything I don't quite like about it, and what I will likely be changing with yet more code.
Latest posts by Larry (see all)
- Warframe Missions: Part 2 – Other Inner Planet Missions - December 22, 2015
- Review: Assassin’s Creed Black Flag - November 22, 2015
- Warframe Missions: Part 1 – the Basic Missions - November 19, 2015