Home >CMS Tutorial >WordPress >Creating a Post Series Plugin for WordPress
A WordPress Post Series plugin enables you to organize your posts serially to create a book or a course. It provides users a path for learning. Posts series plugins can also be used to split a long post into multiple parts.
In this tutorial, I’ll show you how to create a plugin for displaying a series of posts. You can also integrate the same code into a theme, as theme functionality.
In WordPress, taxonomies are used to group or organize similar posts together. But WordPress doesn’t provide a way to display all the posts of a particular taxonomy in a customized, serial manner. WordPress taxonomies are displayed using an archive.php file, so we cannot create a post series as a single, indexable post.
So we need a post series, which is actually one post that contains other posts in a serial manner.
There are many different ways to create a post series. Popular post series plugins found at WordPress.org use custom taxonomies on WordPress posts to create a post series, but in this tutorial I’ll use Custom Post Types instead.
Create a plugin directory named sitepoint-post-series and place two files in this, named sitepoint-post-series.php and sitepoint-post-series.css.
In the sitepoint-post-series.php file, place the code below, so that WordPress recognizes the directory as a plugin and lets you install it.
<span><span><?php </span></span><span> </span><span><span>/* </span></span><span><span>Plugin Name: SitePoint Post Series </span></span><span><span>Plugin URI: https://www.sitepoint.com/ </span></span><span><span>Description: This used is used to create a post series. </span></span><span><span>Version: 1.0 </span></span><span><span>Author: Narayan Prusty </span></span><span><span>*/</span></span>
You can also add post series functionality to a theme. In this case, you will need to place all the code referred to in this tutorial, in the theme’s functions.php file.
First, we need to create a custom post type, where each custom post type represents a post series.
Place the code below in a file called sitepoint-post-series.php:
<span><span><?php </span></span><span> </span><span><span>/* </span></span><span><span>Plugin Name: SitePoint Post Series </span></span><span><span>Plugin URI: https://www.sitepoint.com/ </span></span><span><span>Description: This used is used to create a post series. </span></span><span><span>Version: 1.0 </span></span><span><span>Author: Narayan Prusty </span></span><span><span>*/</span></span>
Here, we created a custom post type with the same taxonomies that are used by WordPress posts. This is so that you can create a category post series too.
We also added activation and deactivation hooks to flush rewrite rules. This is so that the post series can be viewed on the front end.
Here is what our custom post type looks on the admin screen:
Now we need to add meta boxes to the WordPress Posts admin interface. This is so that authors can attach a post to a post series, and provide a serial number to sort the posts inside a post series.
Here is the code to add a meta box to post series:
<span>function sitepoint_post_series_custom_post_type() </span><span>{ </span> <span>register_post_type("sitepoint-postseries", array( </span> <span>"labels" => array("name" => __("Post Series"), "singular_name" => __("Post Series")), </span> <span>"public" => true, </span> <span>"has_archive" => true, </span> <span>"rewrite" => array("slug"=> "post-series"), </span> <span>"supports" => array("editor", "title", "excerpt", "thumbnail", "comments"), </span> <span>"capability_type" => "post", </span> <span>"publicly_queryable" => true, </span> <span>"taxonomies" => array("category", "post_tag"), </span> <span>) </span> <span>); </span><span>} </span> <span>add_action("init", "sitepoint_post_series_custom_post_type", 2); </span> <span>/* Flush Rewrite Rules */ </span> <span>function sitepoint_post_series_activation() </span><span>{ </span> <span>sitepoint_post_series_custom_post_type(); </span> <span>flush_rewrite_rules(); </span><span>} </span> <span>register_activation_hook( __FILE__, "sitepoint_post_series_activation"); </span><span>register_deactivation_hook( __FILE__, "sitepoint_post_series_activation");</span>
Here we add two fields to the meta box. The text field is used by the author to enter the serial number, and the drop down is used to select the post series name to which the post belongs to. If you don’t want to add a post to a post series, then either one or both fields should be left blank.
Here is how it looks on the admin post screen:
Now we need to save the meta box fields when the form is saved. Here is the code to do that:
/* Add Custom Meta Boxes in WordPress Posts */ function sitepoint_post_series_meta_box_markup($object) { wp_nonce_field(basename(__FILE__), "sitepoint-postseries"); ?> <span><span><span><div</span>></span> </span> <span><span><span><label</span> for<span>="sitepoint-postseries-serial-number"</span>></span>Serial Number<span><span></label</span>></span> </span> <span><span><span><br</span>></span> </span> <span><span><span><input</span> name<span>="sitepoint-postseries-serial-number"</span> type<span>="text"</span> value<span>="<span><?php echo get_post_meta($object->ID, "sitepoint-postseries-serial-number", true); ?></span>"</span>></span> </span> <span><span><span><br</span>></span> </span> <span><span><span><label</span> for<span>="sitepoint-postseries-id"</span>></span>Name<span><span></label</span>></span> </span> <span><span><span><br</span>></span> </span> <span><span><span><select</span> name<span>="sitepoint-postseries-id"</span>></span> </span> <span><span><span><option</span> value<span>=""</span>></span>-<span><span></option</span>></span> </span> <span><span><?php </span></span><span> <span>$posts = get_posts("post_type=sitepoint-postseries"); </span></span><span> <span>$selected_series = get_post_meta($object->ID, "sitepoint-postseries-id", true); </span></span><span> <span>foreach($posts as $post) </span></span><span> <span>{ </span></span><span> <span>$id_post = $post->ID; </span></span><span> <span>if($id_post == $selected_series) </span></span><span> <span>{ </span></span><span> <span>?></span> </span> <span><span><span><option</span> selected value<span>="<span><?php echo $post->ID; ?></span>"</span>></span><span><?php echo $post->post_title; ?></span><span><span></option</span>></span> </span> <span><span><?php </span></span><span> <span>} </span></span><span> <span>else </span></span><span> <span>{ </span></span><span> <span>?></span> </span> <span><span><span><option</span> value<span>="<span><?php echo $post->ID; ?></span>"</span>></span><span><?php echo $post->post_title; ?></span><span><span></option</span>></span> </span> <span><span><?php </span></span><span> <span>} </span></span><span> <span>} </span></span><span> <span>?></span> </span> <span><span><span></select</span>></span> </span> <span><span><span></div</span>></span> </span> <span><span><?php </span></span><span><span>} </span></span><span> </span><span><span>function sitepoint_post_series_custom_meta_box() </span></span><span><span>{ </span></span><span> <span>add_meta_box("sitepoint-postseries", "Post Series", "sitepoint_post_series_meta_box_markup", "post", "side", "low", null); </span></span><span><span>} </span></span><span> </span><span><span>add_action("add_meta_boxes", "sitepoint_post_series_custom_meta_box");</span></span>
Here we are saving the meta box content and then calling the function sitepoint_post_series_save_settings with different argument values depending on whether the user is removing a series, adding a series or changing a series.
Here is the code for the sitepoint_post_series_save_settings function
<span>/* Callback to Save Meta Data */ </span> <span>function sitepoint_post_series_save_custom_meta_box($post_id, $post, $update) </span><span>{ </span> <span>if(!isset($_POST["sitepoint-postseries"]) || !wp_verify_nonce($_POST["sitepoint-postseries"], basename(__FILE__))) </span> <span>return $post_id; </span> <span>if(!current_user_can("edit_post", $post_id)) </span> <span>return $post_id; </span> <span>if(defined("DOING_AUTOSAVE") && DOING_AUTOSAVE) </span> <span>return $post_id; </span> <span>$slug = "post"; </span> <span>if($slug != $post->post_type) </span> <span>return; </span> <span>$serial_number = null; </span> <span>if(isset($_POST["sitepoint-postseries-serial-number"])) </span> <span>{ </span> <span>$serial_number = $_POST["sitepoint-postseries-serial-number"]; </span> <span>} </span> <span>else </span> <span>{ </span> <span>$serial_number = ""; </span> <span>} </span> <span>update_post_meta($post_id, "sitepoint-postseries-serial-number", $serial_number); </span> <span>$series_id = null; </span> <span>if(isset($_POST["sitepoint-postseries-id"])) </span> <span>{ </span> <span>$series_id = $_POST["sitepoint-postseries-id"]; </span> <span>} </span> <span>else </span> <span>{ </span> <span>$series_id = ""; </span> <span>} </span> <span>$previous_series_id = get_post_meta($post_id, "sitepoint-postseries-id", true); </span> <span>update_post_meta($post_id, "sitepoint-postseries-id", $series_id); </span> <span>//no series, removing series, adding new series or changing series </span> <span>if($previous_series_id == "" && $series_id == "") </span> <span>{ </span> <span>sitepoint_post_series_save_settings($series_id, $serial_number, $post_id); </span> <span>} </span> <span>else if($previous_series_id != "" && $series_id == "") </span> <span>{ </span> <span>sitepoint_post_series_save_settings($previous_series_id, "", $post_id); </span> <span>} </span> <span>else if($previous_series_id == "" && $series_id != "") </span> <span>{ </span> <span>sitepoint_post_series_save_settings($series_id, $serial_number, $post_id); </span> <span>} </span> <span>else if($previous_series_id != "" && $series_id != "") </span> <span>{ </span> <span>sitepoint_post_series_save_settings($previous_series_id, "", $post_id); </span> <span>sitepoint_post_series_save_settings($series_id, $serial_number, $post_id); </span> <span>} </span><span>} </span> <span>add_action("save_post", "sitepoint_post_series_save_custom_meta_box", 10, 3);</span>
This function creates a string, which stores the WordPress post ID’s that belong to a particular series. And then it stores the strings as a WordPress setting.
Now we’re done with all the admin area code. You should now be able to create posts and assign them to a series. And also assign categories and tags to each series.
Now let’s code the front end to display the post series.
The custom post type is not yet visible in the index and archive pages. To make it visible on these pages as well, you just need to add the code below:
<span>/* Store WordPress posts and Post Series CTY relations as WordPress Settings. */ </span> <span>function sitepoint_post_series_save_settings($series_id, $serial_number, $post_id) </span><span>{ </span> <span>if($series_id != "" && $serial_number != "") </span> <span>{ </span> <span>$post_series_list = get_option("post_series_" . $series_id . "_ids", ""); </span> <span>if($post_series_list == "") </span> <span>{ </span> <span>$post_series_list_array = array($post_id); </span> <span>$post_series_list = implode (", ", $post_series_list_array); </span> <span>update_option("post_series_" . $series_id . "_ids", $post_series_list); </span> <span>} </span> <span>else </span> <span>{ </span> <span>$post_series_list_array = explode(',', $post_series_list); </span> <span>if(in_array($post_id, $post_series_list_array)) </span> <span>{ </span> <span>//do nothing </span> <span>} </span> <span>else </span> <span>{ </span> <span>$post_series_list_array[] = $post_id; </span> <span>$post_series_list = implode (", ", $post_series_list_array); </span> <span>update_option("post_series_" . $series_id . "_ids", $post_series_list); </span> <span>} </span> <span>} </span> <span>} </span> <span>else if($series_id == "" || $serial_number == "") </span> <span>{ </span> <span>$post_series_list = get_option("post_series_" . $series_id . "_ids", ""); </span> <span>if($post_series_list == "") </span> <span>{ </span> <span>} </span> <span>else </span> <span>{ </span> <span>$post_series_list_array = explode(',', $post_series_list); </span> <span>if(in_array($post_id, $post_series_list_array)) </span> <span>{ </span> <span>//here remove the post id from array. </span> <span>if(($key = array_search($post_id, $post_series_list_array)) !== false) { </span> <span>unset($post_series_list_array[$key]); </span> <span>} </span> <span>$post_series_list = implode (", ", $post_series_list_array); </span> <span>update_option("post_series_" . $series_id . "_ids", $post_series_list); </span> <span>} </span> <span>else </span> <span>{ </span> <span>} </span> <span>} </span> <span>} </span><span>}</span>
Here we’re using pre_get_posts hook to add a post series to the $q variable, which is used by the main loop to displays posts.
We need to filter the content of the post series type and add posts belonging to the series.
Here is the code to add posts of a post series in a post series page.
<span>/* Displaying Custom Post Types on Index Page */ </span> <span>function sitepoint_post_series_pre_posts($q) </span><span>{ </span> <span>if(is_admin() || !$q->is_main_query() || is_page()) </span> <span>return; </span> <span>$q->set("post_type", array("post", "sitepoint-postseries")); </span><span>} </span> <span>add_action("pre_get_posts", "sitepoint_post_series_pre_posts");</span>
This displays the posts using HTML unordered list tag. For posts without an image we are loading a image from Lorempixel cloud service to generate random texture images.
We are retrieving the posts of a post series from the setting string, which we saved during the saving of meta data.
We can also add a post series box on posts that belong to a post series to indicate to the user that the post belongs to a specific posts series. Here’s the code to do that:
<span><span><?php </span></span><span> </span><span><span>/* </span></span><span><span>Plugin Name: SitePoint Post Series </span></span><span><span>Plugin URI: https://www.sitepoint.com/ </span></span><span><span>Description: This used is used to create a post series. </span></span><span><span>Version: 1.0 </span></span><span><span>Author: Narayan Prusty </span></span><span><span>*/</span></span>
Here we are just displaying a post series name and which part of this post is from the series.
You can also add the next and previous post of the series by using the below implementation of the sitepoint_post_series_post_content_filter function:
<span>function sitepoint_post_series_custom_post_type() </span><span>{ </span> <span>register_post_type("sitepoint-postseries", array( </span> <span>"labels" => array("name" => __("Post Series"), "singular_name" => __("Post Series")), </span> <span>"public" => true, </span> <span>"has_archive" => true, </span> <span>"rewrite" => array("slug"=> "post-series"), </span> <span>"supports" => array("editor", "title", "excerpt", "thumbnail", "comments"), </span> <span>"capability_type" => "post", </span> <span>"publicly_queryable" => true, </span> <span>"taxonomies" => array("category", "post_tag"), </span> <span>) </span> <span>); </span><span>} </span> <span>add_action("init", "sitepoint_post_series_custom_post_type", 2); </span> <span>/* Flush Rewrite Rules */ </span> <span>function sitepoint_post_series_activation() </span><span>{ </span> <span>sitepoint_post_series_custom_post_type(); </span> <span>flush_rewrite_rules(); </span><span>} </span> <span>register_activation_hook( __FILE__, "sitepoint_post_series_activation"); </span><span>register_deactivation_hook( __FILE__, "sitepoint_post_series_activation");</span>
The problem with this implementation is that the code hits the MySQL number of times equal to the number of posts in the series. There is a performance issue if you have a lot of posts for a particular post series, but I’ve included it for educational purposes.
Here are some of the plugins on WordPress.org that enable you to create a post series. I have compared each with the plugin we’ve created above.
Our plugin is highly customizable and doesn’t include any WordPress hacks. As such, it is much more compatible.
If you own a development blog, then you could use this plugin to create your own post series, which can increase your engagement and conversion rates. You can even use it to split up your large posts into multiple posts.
Feel free to comment on your experiences with the plugin below.
A post series plugin is a tool that allows you to group related posts together into a series. This is particularly useful for blogs or websites that publish content in a serialized format. It enhances the user experience by making it easier for readers to navigate through related content. It also helps in improving the SEO of your website as search engines favor well-structured and interlinked content.
While WordPress categories and tags do allow you to group related posts together, they lack the sequential structure that a post series plugin provides. With a post series plugin, you can order your posts in a specific sequence, making it easier for readers to follow a storyline or a structured learning path.
Yes, most post series plugins offer customization options. You can change the layout, colors, fonts, and other design elements to match the overall aesthetic of your website. Some plugins also allow you to add custom CSS for more advanced customization.
Creating a post series can significantly improve your website’s SEO. By grouping related posts together, you’re creating a rich network of internal links that search engines love. It also increases the dwell time on your website as readers are more likely to read multiple posts in a series.
Absolutely! You can create as many post series as you need. This is particularly useful for websites that cover multiple topics or have different types of serialized content.
Yes, you can add new posts to a series at any time. Most post series plugins allow you to easily manage and update your series, ensuring that your content remains relevant and up-to-date.
Yes, a post series plugin can be used on a multi-author site. It can be a great tool for managing and organizing content from multiple authors, ensuring consistency and coherence across all posts.
No, you don’t need any coding skills to create a post series on WordPress. Most post series plugins come with a user-friendly interface that makes it easy to create and manage your series.
Yes, most post series plugins are designed to work seamlessly with any WordPress theme. However, it’s always a good idea to check the plugin’s documentation or contact the developer for confirmation.
Yes, there are several free post series plugins available for WordPress. However, keep in mind that free plugins may not offer as many features or as much support as premium plugins. Always choose a plugin that best fits your needs and budget.
The above is the detailed content of Creating a Post Series Plugin for WordPress. For more information, please follow other related articles on the PHP Chinese website!