A Custom WordPress Blog Archives Page
Note: This post assumes you know how to use custom page templates in WordPress as well as know how to edit text php files and upload them through FTP. If you are already lost, you can always hire me to make your custom blog archive page for you.
I make a lot of sites that use WordPress as a content management system (CMS) but not with the blog as the front page. For these, I use posts and categories to make various sections of the site using custom templates. My latest example of that is the Blog, Q&A and Latest News sections of the site Hear Florida. For this, I wanted to make an archive page which lists all the categories, subcategories, and posts in what is technically the blog. I am sure someone is going to tell me that a plugin exists to do this thing, but as I tried two that didn’t work well, I had decided to give up and just use PHP. I also wanted to use as many standard WordPress calls as I could instead of just writing all my own functions.
In this exercise, this is what our final product will look like: All Blog Posts Archive » Hear Florida Audiology Group. It was created in a custom template called "All Posts Archive". I will be breaking this down by parts and explaining what each part means to help my readers not only see the code, but to know what each part does. I will break this down piece by piece, but as a preview our final code will look like the chunk below.
<?php
$all_cats = wp_list_categories(‘hide_empty=0&echo=0&title_li=&exclude=1′);
$cats_list = explode("<", $all_cats);
$build_cat_structure = array();
$array_counter = 0;
foreach ($cats_list as $value) {
$string_start = substr($value, 0, 3);
if ($string_start == "li " || $string_start == "/a>" || $string_start == "/li") {
continue;
}
elseif ($string_start == "ul ") {
$build_cat_structure[$array_counter] = "start_child";
$array_counter = $array_counter + 1;
}
elseif ($string_start == "/ul") {
$build_cat_structure[$array_counter] = "end_child";
$array_counter = $array_counter + 1;
}
elseif ($string_start == "a h") {
$cat_name = explode(">", $value);
$build_cat_structure[$array_counter] = $cat_name[1];
$array_counter = $array_counter + 1;
}
}
echo "<ul>";
foreach ($build_cat_structure as $value) {
if ($value == "start_child") {
echo "<ul>\n";
}
elseif ($value == "end_child") {
echo "</ul>\n";
}
else {
$category_id = get_cat_id($value);
echo ‘<li><a href="’ . get_category_link($category_id) . ‘">’ . category_description($category_id) . "</a></li>\n";
$children = wp_list_categories(‘echo=0&child_of=’ . $category_id . ‘&title_li=’);
$find_me = stripos($children, "No categories");
if ($find_me !== FALSE) {
echo "<ul>\n";
$the_query = new WP_Query(‘cat=’ . $category_id);
while ($the_query->have_posts()) : $the_query->the_post(); $do_not_duplicate = $post->ID; ?>
<li><a title="<?php the_title(); ?>" href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php endwhile;
echo "</ul>\n";
}
}
}
echo "</ul>";
?>
The first part pulls the categories and puts them into a list. If you wanted to shape the final outcome of the display, you could change the settings of wp_list_categories() here. For example, setting hide_empty=1 instead of 0, you could hide any categories that you have without posts. I have chosen to exclude the Uncategorized category (category #1), but if you wanted yours listed just removed the exclude=1 part. Or, if you would like to exclude other categories, just list them by number (exclude=1,5,6 for example). The echo=0 is important here because it puts the results into a variable instead of displaying them.
$all_cats = wp_list_categories(‘hide_empty=0&echo=0&title_li=&exclude=1′);
Once the result of wp_list_categories is dumped into the variable all_cats, it is broken apart into text chunks using the character < as the divider.
$cats_list = explode("<", $all_cats);
This basically puts every html chunk into it’s own entry in an array. (If at any point you want to see your results, feel free to do a var_dump($last_variable); and it will show you what you are working with.) I do this to set up the processing of the information in the next set of steps.
$build_cat_structure = array();
$array_counter = 0;
This sets up an empty array which we will fill in the loop below, and starts our array key counter at 0.
foreach ($cats_list as $value) {
$string_start = substr($value, 0, 3);
if ($string_start == "li " || $string_start == "/a>" || $string_start == "/li") {
continue;
}
elseif ($string_start == "ul ") {
$build_cat_structure[$array_counter] = "start_child";
$array_counter = $array_counter + 1;
}
elseif ($string_start == "/ul") {
$build_cat_structure[$array_counter] = "end_child";
$array_counter = $array_counter + 1;
}
elseif ($string_start == "a h") {
$cat_name = explode(">", $value);
$build_cat_structure[$array_counter] = $cat_name[1];
$array_counter = $array_counter + 1;
}
}
This is where I have it to loop through the array I made by the earlier explode() command to set up the final array which will produce the display. By taking the first three letters of each array item as a seed, I can see where the html is going and reflect that in the final build. If the string starts with something that doesn’t influence the final outcome (the start of a list item, the end of a list item, and the end of a anchor tag), the command continue is issued to loop forward on to the next item. If hierarchy is detected (the start or end of an unordered list), a designation is added into the array and the counter advances. If the start of a link is detected ("a h" is the start of a href), it breaks apart that line using explode to pull out the name of the category. The category name is then added to the array and the counter is advanced.
These last parts are where I put it all together and display the data by looping through the array I built earlier ($build_cat_structure). You could probably do this differently or combine the above and below parts instead of looping through twice, but I liked it like this so I could use the data in other ways if I wanted to.
echo "<ul>";
foreach ($build_cat_structure as $value) {
if ($value == "start_child") {
echo "<ul>\n";
}
elseif ($value == "end_child") {
echo "</ul>\n";
}
This makes/ends a nested unordered list If it hits my start/end child marker, which makes the category hierarchy work. This is also a good chance to add specific styling to the inside nest lists, if that is what you want.
else {
$category_id = get_cat_id($value);
The start of the else tells the script what to do if it encounters the name of a category, or something that is not the start or end of a nested list. The next line converts our category name to a category ID using the get_cat_id() function.
echo ‘<li><a href="’ . get_category_link($category_id) . ‘">’ . category_description($category_id) . "</a></li>\n";
This displays the category in a list item with a link to the archive of that category using get_category_link(). I use category_description() here because my template is set up where the category name is a shorter version that is used for the sidebar and the category description is a longer version used for display. If you wanted to use the name instead, just replace category_description($category_id) with $value.
$children = wp_list_categories(‘echo=0&child_of=’ . $category_id . ‘&title_li=’);
$find_me = stripos($children, "No categories");
if ($find_me !== FALSE) {
This special handling function checks to see if the current category is a parent of other categories. For example, on my final page (All Blog Posts Archive » Hear Florida Audiology Group), there is a main category of Blog for which I don’t want the posts listed. I want the posts listed under their sub categories, so it skips the post by post listing if the current category is a parent of other categories. A category that is not a parent of others will have something like "<li>No Categories</li>" as the result of the above wp_list_categories(child_of=) call. The ($find_me !== FALSE) part creates a situation where the posts are only being displayed where the phrase “No Categories” is found.
echo "<ul>\n";
$the_query = new WP_Query(‘cat=’ . $category_id);
while ($the_query->have_posts()) : $the_query->the_post(); $do_not_duplicate = $post->ID; ?>
<li><a title="<?php the_title(); ?>" href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php endwhile;
echo "</ul>\n";
}
}
}
echo "</ul>";
This last part creates another nesting with all of the posts for each category using WP_Query. The posts are displayed with their title and permalinks. Then everything is closed up and all the unordered lists are given end tags.
Overall I am pleased with my results and how it turned out in terms of giving the user a clear way to look through older posts by category and view all posts as a whole.
Tags: categories, category achives, cms, custom template, PHP, plugins, post archives, user experience, web development, website, WordPress, WordPress functions
Aug 03, 2009
What a great job, Nikole! As always, you go outside the box (ie, not just sticking to pre-built WordPress plugins) to find creative solutions to address your client’s needs. Thanks for your help on this project!
Apr 12, 2010
……
Кино фильмы онлайн…
Jun 13, 2010
togpava@yohewgm.ru” rel=”nofollow”>1…
no more…