This tutorial explains how to create a WordPress bookshelf plugin that displays books on a shelf like Smashing Magazine’s eBook page. Some key WordPress functionality will be showcased throughout the tutorial that could benefit your own project.
The article covers how to create post types, shortcodes and meta fields using WordPress’ functionality and how to combine them to make a fully configurable plugin. To begin, we’ll explain how to register the plugin, develop the back-end functionality and then create the front-end display using shortcodes.
Setting Up The Plugin
The standard method of registering a plugin in WordPress is to add some information to the header of the file. Create a file named sm_books.php
, and add the information below to it. Note that the information being registered is “Plugin Name,” “Author,” “Version,” etc. This information will be used to tell WordPress about the plugin so that the plugin can be activated and displayed in the plugin management screen.
<?php
/*
Plugin Name: SM Books
Plugin URI: http://b4ucode.com
Description: Displays Books and books
Author: B4uCode
Version: 1.0.0
Author URI: http://b4ucode.com
*/
To learn more about creating a plugin, check out “WordPress Essentials: How to Create a WordPress Plugin.”
Register The Post’s Type
In order to add the new book system, we will register a new custom post type using the register_post_type
function. To access this function, we will trigger it using the add_action
function. Add the following to the sm_books.php
file:
//Register Book Post Type
add_action( 'init', 'create_sm_book_type' );
function create_sm_book_type() {
register_post_type( 'sm_books',
array(
'labels' => array(
'name' => __( 'Books' ),
'singular_name' => __( 'Book' )
),
'public' => true,
'has_archive' => true,
'supports' => array('title','editor','thumbnail')
)
);
}
This snippet is a basic way to create a post type. The register_post_type( $post_type, $args )
function takes two parameters: $post_type
and $args
. The first parameter is a 20-character string that will be used for the name of the new type. The default post types in WordPress are “Post,” “Page,” “Attachment,” “Revisions” and “Navigation Menus.” These default names cannot be used when creating a custom type, so we will use sm_books
. The second parameter is an optional array that stores a multitude of options for the post type. The array accepts “labels” that will be used and seen while using sm_books
, as well as options available for the post type, such as exclude_from_search
, show_ui
and much more.
Add Books Category
For this tutorial, we will add a custom set of categories for the books. This set is referred to as a “taxonomy,” and we will create it with the register_taxonomy
function, which we will call sm_book_category
. The categories enable us to assign our entries to different categories for displaying on the screen. Just as with our previous snippet in the file, we will use add_action
to trigger our function. Also, register_taxonomy($taxonomy, $object_type, $args)
is very similar to the register_post_type
function, with its three parameters:
$taxonomy
A string with no capital letters or spaces.$object_type
Defines the post type that this new taxonomy will be attached to.$args
An optional array that holds options and labels similar to what we see in theregister_post_type
function.
//Add Book Categories
add_action( 'init', 'sm_book_taxonomies', 0 );
function sm_book_taxonomies(){
register_taxonomy('sm_book_category', 'sm_books', array(
'hierarchical'=>true,
'label'=>'Categories'
)
);
}
Add Meta Fields
As you may have noticed, each book has different attributes, consisting of prices and links. We will add these attributes as custom meta data fields using the add_meta_boxes
action in WordPress. At the moment, we will also add the save_post
action to save these fields. Once we’ve triggered our function, the add_meta_box( $id, $title, $callback, $post_type, $context, $priority, $callback_args )
function will establish the “ID,” “Name” and “Description” of the meta box area. The other $post_type
parameter determines what post types the meta box should appear in; and for the $callback
, we will use the sm_bk_info_box
function, which will render the HTML output of form fields.
add_action( 'add_meta_boxes', 'sm_book_extra_box' );
add_action( 'save_post', 'sm_books_save_postdata' );
function sm_book_extra_box() {
add_meta_box(
'sm_bk_info_box',
__( 'Book Information', 'sm_bk_info_box' ),
'sm_bk_info_box',
'sm_books',
'side'
);
}
/* Prints the box content */
function sm_bk_info_box( $post ) {
$price = get_post_meta( $post->ID, 'price', true );
$sale_price = get_post_meta( $post->ID, 'sale_price', true );
$link_amazon = get_post_meta( $post->ID, 'link_amazon', true );
$link_google = get_post_meta( $post->ID, 'link_google', true );
$link_apple = get_post_meta( $post->ID, 'link_apple', true );
// Use nonce for verification
wp_nonce_field( plugin_basename( __FILE__ ), 'sm_book_noncename' );
?>
<p>
<label for="price">Price
<input type="text" name="price"
id="price" size="10" value="<?php echo $price; ?>" />
</label>
</p>
<p>
<label for="sale_price">Sale Price
<input type="text" name="sale_price"
id="sale_price" size="10" value="<?php echo $sale_price; ?>" />
</label>
</p>
<p>
<label for="link_amazon">Amazon Link
<input type="text" name="link_amazon"
id="link_amazon" size="25" value="<?php echo $link_amazon; ?>" />
</label>
</p>
<p>
<label for="link_google">Google Link
<input type="text" name="link_google"
id="link_google" size="25" value="<?php echo $link_google; ?>" />
</label for="myplugin_new_field">
</p>
<p>
<label for="link_apple">Apple Link
<input type="text" name="link_apple"
id="link_apple" size="25" value="<?php echo $link_apple; ?>" />
</label>
</p>
<?php
}
To save the meta data fields that we created previously, we will create the sm_books_save_postdata
function that we defined in our save_post
action. Within this function, we will check for submitted post data and update the post meta data using the update_post_meta
function. Add the following snippet to the sm_books.php
file to give the plugin an update-able set of custom fields:
function sm_books_save_postdata($post_id){
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
return;
if ( !wp_verify_nonce( $_POST['sm_book_noncename'],
plugin_basename( __FILE__ ) ) )
return;
if ( !current_user_can( 'edit_post', $post_id ) )
return;
if( isset( $_POST['price'] ) ){
update_post_meta( $post_id,'price',
esc_attr( $_POST['price'] ) );
}
if( isset( $_POST['sale_price'] ) ){
update_post_meta( $post_id,'sale_price',
esc_attr( $_POST['sale_price'] ) );
}
if( isset( $_POST['link_amazon'] ) ){
update_post_meta( $post_id,'link_amazon',
esc_attr( $_POST['link_amazon'] ) );
}
if( isset( $_POST['link_google'] ) ){
update_post_meta( $post_id,'link_google',
esc_attr( $_POST['link_google'] ) );
}
if( isset( $_POST['link_apple'] ) ){
update_post_meta( $post_id,'link_apple',
esc_attr( $_POST['link_apple'] ) );
}
}
The update_post_meta
takes the post’s ID as the first argument, the key to update as the second argument and the value to be saved as the third argument.
Add Featured Post
For our custom book system, we will add an option for a thumbnail, which will be used to show the book cover on our shelf. We will use the featured post’s thumbnail to accomplish this, and we’ll set the image size that we intend to use with the add_image_size
function.
//Enable Thumbnail
if ( function_exists( 'add_theme_support' ) ) {
add_theme_support( 'post-thumbnails' );
set_post_thumbnail_size( 150, 150 );
add_image_size( 'book-thumb', 84, 107, true );
}
The name of the thumb that we will be referencing is book-thumb
, and the size that we will try to resize to is 84 × 107 pixels. These are optional, but based on what we’re going for, the numbers suit our needs.
Further Reading on SmashingMag:
- A Beginner’s Guide To Creating A WordPress Website
- How To Create Tabs On WordPress Settings Pages
- How To Contribute To WordPress
- Diary Of A WordCamp
Add Shortcode
Now that we’ve created the administrative side of the plugin, we will create the front-end design. For this tutorial, we will use a WordPress shortcode to add our book listing to the page. Our shortcode will look like the following on any page:
[sm_books category="coding"]
The shortcode above will be used to display the list of books in the category of “coding.” Note that “coding” is the slug of the custom taxonomy that we created. In the end, the plugin will be able to list all of the books if we leave out the category
attribute of the shortcode.
Now, let’s move on to making the shortcode work. Add the following code to the sm_books.php
file:
function sm_display($atts) {
extract( shortcode_atts( array('category' => ''), $atts ) );
$args = array('post_type'=>'sm_books', 'sm_book_category'=>$category);
$posts = new WP_Query( $args );
$html = '<div class="sm_holder"><div class="shelf"><div class="innerDiv" id="sm_book_1">';
// Book Loop
if ( $posts->have_posts() ) : while ( $posts->have_posts() ) : $posts->the_post();
$book_cover = get_the_post_thumbnail(
get_the_ID(),'book-thumb',
$attr=array("alt"=>get_the_title())
);
$html .= '<a href="'.get_permalink().'" class="books">'.$book_cover.'</a>';
endwhile; endif;
$html.='</div></div><table class="sm_book_tbl" cellspacing="0" cellpadding="0">';
// The Loop
if ( $posts->have_posts() ) : while ( $posts->have_posts() ) : $posts->the_post();
$price = get_post_meta( get_the_ID(), 'price', true );
$sale_price = get_post_meta( get_the_ID(), 'sale_price', true );
$link_amazon = get_post_meta( get_the_ID(), 'link_amazon', true );
$link_google = get_post_meta( get_the_ID(), 'link_google', true );
$link_apple = get_post_meta( get_the_ID(), 'link_apple', true );
$html.='<tr><td class="title"><a href="'.get_permalink().'">'.get_the_title().'</a><br>';
if ($link_amazon):
$html .= '<small><a style="color:#999" href="'.$link_amazon.'">Amazon</a>';
if ($link_google || link_apple):
$html .=' | ';
endif;
endif;
if($link_google):
$html .='<a style="color:#999" href="'.$link_google.'">Google</a></small>';
if($link_apple):
$html .=' | ';
endif;
endif;
if($link_apple):
$html .='<a style="color:#999" href="'.$link_apple.'">Apple</a></small>';
endif;
$html .= '</td><td>';
if ($sale_price && $price) {
$html .= $sale_price.'<br />';
$html .= '<span class="old_price">'.$price.'</span>';
} elseif ($price) {
$html .= $price;
} else {
$html .= '';
}
$html .= '</td>
<td class="cart">
<a style="margin:0px" class="sm_cart_button" href="'.get_permalink().'">Add to Cart</a>
</td>
</tr>';
endwhile; endif;
$html .= '</table>';
$html .= '</div>';
return $html;
}
In the snippet above, we have created a couple of loops that will be rendered when the shortcode is entered. By instantiating the WP_Query
class, we are creating a couple of loops to display the books. The arguments that we will use are post_type
of sm_books
; then, we will use the argument of sm_book_category
, which is querying a taxonomy. The value we add will be derived from the shortcode.
The first loop renders the book’s cover in a div where the shelf image will be displayed. The second loop places a set of rows below the shelf and outputs some information about each book. The template tags are used as follows:
get_permalink()
Fetches the permalink.get_the_ID()
Fetches the post’s ID, which is combined withget_post_meta
to get the meta fields.get_the_title()
Fetches the title.
The final bit for the shortcode is the action that actually registers the shortcode. The first argument is the string that will be written to call the shortcode. The second is the function that will be executed. Add the following below your function:
add_shortcode( 'sm_books', 'sm_display' );
Styling Our Listing
Looking at what we have so far, you can imagine how out of place everything looks. Therefore, at this stage, we will add some CSS to style our output. Create a folder named sm_books
. Then, create a file named style.css
, and add the following code:
.sm_holder {
padding: 0px;
border-bottom: 5px solid #41B7D8;
width: 630px;
}
div.shelf {
background-image: url(shelf_bg.jpg);
display: block;
}
.shelf div.innerDiv {
padding: 0px 34px;
width: 100%;
}
.shelf .books img {
margin-right: 10px;
padding-top: 15px;
margin-bottom: 11px;
}
span.old_price {
color: #E53B2C;
text-decoration: line-through;
}
.sm_book_tbl {
margin: 0px 20px 0px 0px !important;
width: 100%;
background-color: #f3f3f3;
border: 1px solid #e5e5e5
}
.sm_book_tbl td.title {
height: 60px;
width: 70%;
padding-left: 20px;
padding-right: 20px;
color: #999
}
.sm_book_tbl td.cart {
padding: 10px 20px;
color: #999;
}
In our style sheet, we have added a background image to our shelf
div, as seen in the declaration for the div.shelf
class. This image will be located in the sm_books
folder. Attached to this tutorial is the source file; add the shelf_bg.jpg
file to that folder.
Once completed, we will attach the style sheet to our plugin. Add the following snippet to the bottom of the sm_books.php
file. Using some WordPress functions, we will register the style sheet from our folder with the WordPress system.
function sm_add_styles() {
wp_register_style( 'sm_add_styles',
plugins_url('sm_books/style.css', __FILE__) );
wp_enqueue_style( 'sm_add_styles' );
}
add_action( 'wp_enqueue_scripts', 'sm_add_styles' );
Download the plugin
You can download the B4uCode Smashing Books plugin, which contains everything covered in this tutorial.
Conclusion
Having done this tutorial, you should be able to create a nice shelving plugin for your books. The plugin might serve your needs if you need an online book archive or library. The options aren’t limited to books either; you could create a similar system for CDs, DVDs and records, and you could tweak it to show videos. The possibilities are endless.
Resources From the WordPress Codex
- “ShortCode API”
- “Writing a Plugin”
- “Function Reference/register taxonomy”
- “Function Reference/add meta box”
- “Post Types”