Set up your posts:
The first thing you will need is at least two posts. You need to create a Key named “Series Name” and assign it to each post. You also need to come up with an actual name for this series, then put that in the Value box. The Key and Value need to be the same for each post. Otherwise, this won’t work.
Modify the code:
Now, open “single.php” from your theme directory. Scroll to the bottom and find the closing </div> that ends the post. This will be different with individual themes. You can place this wherever you like. My code is after the post and before the comments template.
Insert this code:
<?php // Checks to see if the post is in a series
// Get Series Name
$series_name = get_post_meta($post->ID, 'Series Name', $single = true);
// If post is in a series
if($series_name !== '') {
// Echo the list header
echo '<h3>Other articles in the ' . $series_name . ' series:</h3>';
Basically, this checks to see if your article is in a series at all. If it is, a header for your list is displayed. If it’s not, then the rest of the code won’t run.
Now, we need to query the database for posts specifically with the same series name as this post. We do this by narrowing the query down to the post meta Key and post meta Value.
// Query the database for the posts
$query_string = "
SELECT *
FROM $wpdb->posts
LEFT JOIN $wpdb->postmeta ON ($wpdb->posts.ID = $wpdb->postmeta.post_id)
WHERE $wpdb->postmeta.meta_key = 'Series Name'
AND $wpdb->postmeta.meta_value = '$series_name'
AND $wpdb->posts.post_status = 'publish'
AND $wpdb->posts.post_type = 'post'
ORDER BY $wpdb->posts.post_date ASC
";
All that’s left to do now is output the posts in a nice, neat list. I’m currently using an unordered list (<ul>), but you can easily change this to an ordered list (<ol>). Add this last bit of code and you’re done.
// List the posts
$series_posts = $wpdb->get_results($query_string, OBJECT);
if ($series_posts):
echo '<ul>';
foreach ($series_posts as $post):
echo '<li>'; ?>
<a href="<?php echo the_permalink(); ?>" title="<?php echo the_title(); ?>">
<?php echo the_title();
echo '</a></li>';
endforeach;
echo '</ul>';
endif;
rewind_posts();
} // End check for series
?>
This is a little more complicated than some of our other scripts in the Wordpress custom field series because of the database query. If you noticed, I changed a little something with the naming of the Key in this post of the series. Do you know what it is?
I capitalized the name and used a space between the words: “Series Name.” In the previous posts, this would have looked like “series-name.” The reason I changed, was to show you a different way to name your Keys. You should note that custom field Keys are case-sensitive.
What if I use a related entries plugin?
I use a related posts plugin on this site, and this is quite useless when I’m customizing my related posts with this method. I’m going to fix this little problem by using a PHP “else” statement.
So, if this post is in a series, my related posts are replaced by my list of the posts in the series. The related posts plugin is used if the post is not in a series.
<?php
else {
if(function_exists('related_posts')) { ?>
<h3>Related Posts</h3>
<ul>
<?php related_posts(); ?>
</ul>
<?php }
} // end else ?>
Custom post titles in the list:
If you want to add custom titles to individual articles specifically for this list, you can create a Key named “Series Article” and give it a Value of “Your Custom Title.” This might be useful if your titles are something like “Example Series: Bla Bla Bla” and “Example Series: Yada Yada Yada.” You may want to remove the “Example Series” part because your readers will already know what series of articles this is.
In the above code, replace the code between the “foreach” and “endforeach” with this:
// get article titles
$series_article = get_post_meta($post->ID, 'Series Article', $single = true);
echo '<li>'; ?>
<a href="<?php echo the_permalink(); ?>" title="<?php echo the_title(); ?>">
<?php if($series_article !== '') echo $series_article; else echo the_title();
echo '</a></li>';
Pages: 1 2

Or, you could just use the In Series plugin instead. Benefits include a pretty UI for adding posts to a series, automatic link insertion (no theme hacking required), and no PHP skills needed. Give it a try, I’m sure you’ll love it.
Thanks Quandary for stopping by. While I’m sure the plugin is great, this tutorial series isn’t really about the specific things I cover. It’s about learning to use custom fields.
The main goal here is to play with different ways to display content and extend WordPress. This sometimes means not having to find just the right plugin for your needs.
I much prefer writing the code myself as opposed to using a plugin. One reason is because some plugin authors eventually stop supporting their plugins (this is not to say that you’ll do this). Eventually, I turn these “hacks” into plugins for use on my site, and sometimes release them to the public.
Mostly, this tutorial series is about allowing others to learn the system. If we all use plugins for everything, then who’ll be the next generation of plugin developers?
If we all write our own, how will we get anything else done? How will the people who can’t write their own ever find one that does everything they need, instead of what the developers need? And if you maintain everything yourself anyway, how is it a loss to pick up an already working, already supported plugin — even if the developer keels over dead the day after you install it?
I understand what you’re saying here. However, consider how I found this page: I was checking up on search engine keyword rankings, and this post kept coming up over, over, and over again as a contender with the likes of Organize Series, In Series, and articles describing how to implement series with these plugins. In that context, this is very much a “check out this solution” post. In the context of “learning how to use custom fields,” it’s a functional, topical toy. My main interest here is to highlight the latter over the former, because there are much more complete solutions available (and I may have happened to invested a few hundred hours and some pride in one of them…
).
As for nurturing budding hackers — re-use is a cornerstone of good development practice, and constructive laziness (the ability to do a cost-benefit analysis on work, over the long-run) is a hallmark of a great developer. Learning how to find what you need helps prevent wasted effort, and allows everyone to work together to make something that’s better than what we could make by ourselves. It’s a skill that, in my opinion, is just as essential as being able to learn how a system works. Furthermore, being able to read and understand other people’s codebase is an absolutely critical skill that you cannot gain by writing everything yourself.
Getting in the habit of self-supplying can also lead to Not Invented Here Syndrome (not that you suffer from it, but I’ve dealt with several groups that have). In these cases, doing it “in-house” starts to become more valuable than actually finishing the product — usually with chants of “we understand the codebase better” and “we have more control this way.” It’s easy to waste vast amounts of time and energy in writing systems from scratch, at best canceling out any benefits gained from internal production. In the professional world, it hurts the bottom line; in the personal world, it’s self-indulgent at best (not necessarily a bad thing), and an unfortunate waste of time at worst.
I think my last line didn’t sound exactly right because you bring up a good point. “Re-use is a cornerstone of good development.” I totally agree. I pretty much agree with everything you said.
All I’m saying is that this is a tutorial series on learning to use custom fields. This is code that others can use or “re-use” to develop bigger and better things. Mostly, it’s an experiment for me. I’m learning to use custom fields in different ways as I go.
Sure, there may be better and easier ways to do things, and I’m glad you pointed out your plugin. I haven’t tested it, but I’ve read the page you linked to and it looks great. People should definitely use it for things like this, if that’s what they want.
I think I may have sounded like I’m becoming an “in-house” type of developer with my last comment, but this is far from the truth. If this was the case, I’d still be working on making my own blogging system. I just want to continue learning and then provide what I’ve learned back to the community. It’s up to the community to decide whether they want to use it.
One point I do disagree on is that it’s “an unfortunate waste of time.” I don’t think it’s a waste of time because this is what I enjoy doing and how I enjoy doing it. Especially since this blog is not part of the “professional world.” It’s a personal blog where I don’t have a deadline to meet or a job that just has to get done. It’s my Web experience.
As far as popping up in the search rankings, there’s not much I can do about that, except for make my site worse.
I’m really hoping to go up in the search rankings for custom field tutorials though.
*lol*
No, no, you need to blast your page right now!
We are, it appears, in violent agreement. I really do appreciate you putting the effort into documenting the process as you go; I’ve meant to do the same thing many times over, but I’m better at mentoring one-on-one than conveying information in more general write-ups. I’d be happy to share my techniques and experiences with you, if you think they’d be helpful; I’d love to see that information passed on in a more accessible manner.
Hello,
I just wanted to thank you for putting up this tutorial.
I recently was having problems with In Series (it seems to be clashing with one of my other plugins or something else on my site) and I was looking to find another solution (Plus, the recent in-series upgrades have now eliminated the possiblity of displaying the series in a sidebar, and since I can’t downgrade…). It’s still a great plugin, it just doesn’t seem right for my site at the moment.
Searching for a new solution, I first stumbled across Organize Series…only to discover that it doesn’t work with WP 2.3.
Thinking I was out of luck, I stumbled across your site…and it was exactly what I was looking for.
Reid
Well, thanks for using it. It’s not the most elegant solution as far as listing articles in a series, but it definitely works.
This is great stuff. I’m trying to do something similar, but listing related posts for a single post based on the tags of the main post. I’ve explained it a hair better here:
http://wordpress.org/support/topic/162462?replies=1
You obviously have a deeper PHP understanding than I do and I’ve tried to modify your code to fit for 2 days (I wish I was exaggerating). Do you have any ideas how I can create a secondary loop, on single.php, that’ll list any posts using the same tag(s) the main post does without including the main post itself. It seems easy conceptually but damned if I know…
you save my life…..thank you
Great tutorial – thanks.
I have one question though. How do add a check to ensure that other posts in the series are actually published?
For example, I may write a series that is published over several days. When I write the post I will add the key and let WP take care of the scheduling. BUT when the first of the series is published it shows the h3 and an empty list until the next one is published.
How can I avoid that?
Great tutorial, Justin. Thanks for taking the time to explain it to us all, much appreciated. While I do like existing plugins, I definitely like to write my own stuff too ’cause, well, I can tweak it just the way I want, plus I learn quite a bit in the process.
@Quandary, you don’t have many friends, do you? You need to step away from the computer and socialize a bit.
Wow, this is great! Thanks!
I wanted to have the series list only the other articles, not relist the article the reader was visiting, so I added this line to the SQL Query:
AND $wpdb->postmeta.post_id != $post->IDjust before the ORDER BY line.
Just thought someone else might find that helpful. “-)
Oops, forgot one other note…. my current theme is really a really old, pretty basic theme I slammed together when WP was first released. Being too lazy to redo much, I patch and hack as necessary.
To use the PHP code provided in this article, I had to remove the
// rewind_posts();(As you can see I commented it out in case I need it if I ever update my theme.)
Without removing this line, it caused the posts on my index page to repeat — again, I’m sure this is because I’m using some really old code here and there.
Just a note for other slackers like me!
Good morning,
Thanks for providing this information! The plug-ins: In Series and Organize Series are both broken… In Series is no longer supported, and Organize Series broke with WP 2.63. I have been working with your code, it is exactly what we need; however, it seems something is wrong with the rewind_posts() function. If I leave the rewind in our server just grinds, if I take it out the comments following the post content are from the last post in the series
Please help, we will pay if necessary!
Thanks again for the info,
Ministermark
Remove
rewind_posts(). Change it towp_reset_query().Justin,
Nice article – I was looking for something exactly like this! Thanks.
A follow up on Custom Post Templates would be nice (hint, lol). After all, these Custom Fields are great (I use them a lot on various sites), but they can be a bit of a nightmare for the average user to remember when writing posts.
Define what a “Custom Post Template” is.
I’ve actually got a better way to do this, and it’s implemented in my Hybrid theme.
Justin,
Clearly what was in my mind when I posted the comment didn’t make it’s way from my brain to my typing fingers, lol.
What I mean is creating Custom Write Post “templates” (when in WP Admin>Write Posts) so that, for example, compulsory custom field keys are already listed and the post author is then better prompted to add a Value. Just an idea.
Anyway, in the meantime, I’ll take a look at your Hybrid Theme.
Wow really useful!
Thanks for this series on custom fields!
I currently use a related post by category plugin, but I was looking for a way to tie together specific articles. I thought custom fields may be the answer, and your blog post helped confirm that.
Unfortunatey, I’m just on the verge of a redesign, so I hesitate to move forward with modifying the template files at this time. I did read your rant on premium themes, but I do think that’s the biggest merit to the thesis theme – they externalize all the custom functions so that they’re not within the template files themselves.
But that’s neither here nor there — just wanted to say thanks for the information. I read through several of your posts and really enjoyed — will be subscribing!
Andrea
I believe Thesis has a hook after the post, so you wouldn’t have to add this into the templates at all if you’re using it. I’ve actually done the same thing with my Hybrid theme, which has a much better implementation of this where all you have to do is type in the name of the series in a custom meta box I’ve added.
OK folks. It was long overdue, but I updated the article to reflect a an easier way to handle this.
very nice indeed, keep the good work, bookmarking this
This is great, thank you for this. Simple and effective.
How you can list the posts in the series in chronological order? The code, as is, displays in reverse chronological order.
Hi,
thanks for a great code!
Just a question. I replaced rewind with wp_reset_query(); However, the id of the last post of the series is retained. how do I reset to current post?
I solved the problem.
….
stuff
more stuff
…..
etc.
Hi!
I’d like to know if it’s possible to make a similar function with 2 values.
Example: I’ve got an article for a brand in a category called /brands/. I’d like to show 2lists: a list of 5 news (category “news”) from this brand , a list of 5 press releases (category “press-releases”) from this brand.
I don’t know if it possible. Should I add a custom field only for the brand, or for the brand and the type of article (News / Press Releases). Can we cross 2 key and verify if the value is the same?
PS: I’m french, my english is not really good so I hope you understood my question^^
I found by myself:
Now i just have to call the function like it:
* or another field
** or another category
Some code deleted by the administrator because it was not properly input.
All very good, perhaps, for the ones already developed. For the neophyte, absolutely unintelligible. Sorry.. But I wonder when a tutorial will be written in plain English that sets someone up right from the base?
Hum Hum !
I think I’m not enough good cause whan I follow this help, I have two time the same things like this :
Articles en relation
* test d’un nouvelle article
* test pour article dans cat vladana
* test pour article dans cat vladana
* test de page 19/05/09
* test de page 19/05/09
I don’t understand why ?!?
More, I try to delete the line where is the title of the post where I’m but I didn’t succed. I try to add “AND $wpdb->postmeta.post_id != $post->ID” but without success !
After, I search to add the thumnail of the post next to the related post link !
I know, I know, first, my english is not really good, second, my php is worth…
Somebody to hell me ?
Thanks for this help
Julien
vladaju.fr
Ok ! I found the problem, why he put two times the lines !!! When I validate custom field, wp enter two times the line ! I was in local, maybe it’s cause of this…
So, I will search to add thumbnail… It’s will be more difficult…
Julien
If I add the in single.php, how to make if no any series post -> show ” No series post”. Thanks.
Thank you for great piece of code!
Is it possible to go even further and divide resulted list in two sub lists?
One with “old” and another with “current” or “future” posts (using another custom field to set some date).
Justin,
your comment from November 10th helped me with my mini loop problems after upgrading to WP 2.8.4.
Thanks a lot!
Hi Justin, great article, very helpful.
Is it possible to list all the values of a certain key?
For example, i’m making a gallery site, and i have a custom field called “artist”, my client would input the name of the artist when writing each new post.
I want to list all the artists, so, all the values that have been typed into the Artist custom field.
I’m sure this is possible but can’t work it out.
Thanks,
James
Great stuff Justin.
Is there a way to show only the other items in the series–to exclude the title of the article you’re currently viewing?
Hi! Thanks for this nice script!
I have created a little “addon-script”, if you want to change the order of the posts in a series. Maby you write 5 posts, but decide that the order of the posts is not the same order that you write the posts… Maby the last post you write should be the first post in the series.
You have to add another custom field, in this script I use “Series_part”, to hold the order of the post you are editing.
Here is the sorting script:
And then you need to add the following line to the original script, so that the posts are sorted before they are printed.
It has to be inserted right after:
This is great, been searching for something like this for a while. It’s almost perfect for what I need it to do!
Is it possible to replace the outputed post ID with an image which is stored in a different custom field?
If you look at the post page here: http://www.violetrosevintage.com/nang/?p=112
I want to replace the post id under the post with the post-icon for that artist. Similar to the ‘Recent Releases’ on the right, only specific to the artist of each post.
Is this possible? I’ve tried amending your code but having no luck!
Thanks
it’s ok.. I sorted it! Hadn’t read page 2!
Hi Rich,
I’d love to hear how you did it??
Thanks
I can’t say thank you enough! Not only for this post but for all the other various bits and pieces of info you have scattered all over the web. Your name comes up quite a bit and very few people explain things as well as you do. As I am new to all this I find most of the info assumes that you are already a php wiz which I am not.
I was not looking forward to attempting the task explained in this post because all the info I found elsewhere was way to complicated. I was able to impliment this in about 15 minutes and got it working straight away! The only place I stumbled up was when I first pasted the code into functions.php and got an error. Once I removed the <?php tags it worked perfect. I was hoping you could answer what is probably a stupid question for a beginner…
Why is a <?php tag always shown in examples even when you don't need to be pasting it into the desired file?
I don't know if that is a stupid question or not but it is something that always confuses me. Well, thanks again for your help on this one it has made things much easier!
Gah..
I’ve been using your code (Thank you!) for some time and love it…but after moving domains and upgrading to 3.3.1 and StandardTheme 2.7.2 it’s not working anymore….
Standard theme changed the post call, but that’s just figuring out how to make things pretty again, I can’t figure out why the function doesn’t seem to be doing anything.
Seems like a little frustration will work for you sometimes… either the theme or wordpress…or something else that got changed in the move is more concerned with capitalization on the keyword….
And, if anyone is looking to get the inside the div of the post using standard theme 272, you have to modify loop.php rather than single.
Thanks Again!