Custom single template for a specific category
What is the best way (performance & code structure) to create a custom template for a WordPress Post, which belong to a specific category? I realized that you can’t just create single-catname.php – and how to include all the sub/parent and so on categories to? Not just the main category…Attempt 1: Added to functions.php (Filter) – you need to create single-enter-editus.php – but otherwise theme uses original single-template
function get_custom_cat_template($single_template) { global $post; if ( in_category( 'enter-editus' )) { $single_template = dirname( __FILE__ ) . '/single-enter-editus.php'; } return $single_template; } add_filter( "single_template", "get_custom_cat_template" ) ; </pre>
Attempt 2: Put the following Code in to single.php (instead of all other code) and create a single-template.php (with the code from the single.php) & a custom single-movies.php
<?php if(has_term('enter-editus', 'category', $post)) { get_template_part('single-enter-editus', 'enter-editus'); } else { // use default template file single-template.php get_template_part('single-template'); } ?>
Filters – cleaner
My opinion, use what you are comfortable with. If there are any performance difference it will be minute/irrelevant. My preference, use the filter.To come to your real concern/question, in my opinion, the best approach will be to use the parent category ID and work from there. It will be the least resource intensive to work from here. Reverse engineering can become quite an unnecessary waste of resources.
Make use of get_categories to get the child categories from the given category. You can make use of either one of two parameters, either parent or child_of
parent (integer)
Display only categories that are direct descendants (i.e. children only) of the category identified by its ID. This does NOT work like the ‘child_of’ parameter. There is no default for this parameter. [In 2.8.4]
child_of (integer)
Display all categories that are descendants (i.e. children & grandchildren) of the category identified by its ID. There is no default for this parameter. If the parameter is used, the hide_empty parameter is set to false.
Once you have these, use wp_list_pluck to get the catID, name or slug fields from the returned array of categories. This array will be used to check if a post belongs to one of these categories. You can either use has_category or in_category
This is how you can extend your code to make sure that posts belonging to either the parent category or its descendants uses the given template
add_filter( 'single_template', function ( $single_template ) { $parent = '618'; //enter-editus cat id $categories = get_categories( 'child_of=' . $parent ); $cat_names = wp_list_pluck( $categories, 'name' ); if ( has_category( 'enter-editus' ) || has_category( $cat_names ) ) { $single_template = STYLESHEETPATH . '/single-enter-editus.php'; // dirname( __FILE__ ) . if putting in functions.php } return $single_template; //if not enter-editus then use regular single template }, PHP_INT_MAX, 2 );
dirname( __FILE__ ) .
When you include something, you use the file path because it’s a local file and you’re reading into the environment right here and now and using that code.
When you “enqueue” something, you’re not reading the file in, you’re sending the URL of the file to a system that puts that URL in the resulting output webpage, for the viewer’s browser to then load and read.
You use a file path when the PHP code is manipulating the file. You use a URL when the browser needs to see that URL and retrieve the file itself.
Child themes reference parent themes by directory name, and in a normal install all your themes live in wp-content/themes/, so I’d say it’s fine to reference those themes by their relative path:
include ‘../parent-theme/some-file.php’;
If that makes you uncomfortable, I observe the following constants in WordPress 3.0.1 with a twentyten child theme called tt-child:
TEMPLATEPATH /home/adam/public_html/wp3/wp-content/themes/twentyten
STYLESHEETPATH /home/adam/public_html/wp3/wp-content/themes/tt-child
So you can do the following in your child theme to reference the parent theme directory:
include TEMPLATEPATH . '/some-file.php';
if ( has_category( 'enter-editus' ) || has_category( $cat_names ) ) { $single_template = dirname( __FILE__ ) . '/single-enter-editus.php'; } BECOMES if ( has_category( 'enter-editus' ) || has_category( $cat_names ) ) { $single_template = STYLESHEETPATH . '/single-enter-editus.php'; }Create the single-enter-editus.php from current single.php. Edit as you desire.
Showing categories and subcategories with posts
Basically as the title says I want to get list of categories and subcategories and then posts(with links to them) for those categories/subcategories.
This is the structure I'm trying to achieve:
Category 1
Subcategory 1 within category 1
- Post 1 within subcategory 1
- Post 2 within subcategory 1
- Post 3 within subcategory 1
Subcategory 2 within category 1
- Post 1 within subcategory 2
- Post 2 within subcategory 2
- Post 3 within subcategory 2
Subcategory 3 within category 1
- Post 1 within subcategory 3
- Post 2 within subcategory 3
- Post 3 within subcategory 3
Posts that have no subcategory
- Post 1 with no subcategory
- Post 1 with no subcategory
Category 2
Subcategory 1 within category 2
- Post 1 within subcategory 1
- Post 2 within subcategory 1
- Post 3 within subcategory 1
Subcategory 2 within category 2
- Post 1 within subcategory 2
- Post 2 within subcategory 2
- Post 3 within subcategory 2
Subcategory 3 within category 2
- Post 1 within subcategory 2
- Post 2 within subcategory 2
- Post 3 within subcategory 2
Posts that have no subcategory
- Post 1 with no subcategory
- Post 1 with no subcategory
Now so far after after reading everything I could found on the subject I have the following code:
<ul>
<?php
$get_parent_cats = array(
'parent' => '0' //get top level categories only
);
$all_categories = get_categories( $get_parent_cats );//get parent categories
foreach( $all_categories as $single_category ){
//for each category, get the ID
$catID = $single_category->cat_ID;
echo '<li><a href=" ' . get_category_link( $catID ) . ' ">' . $single_category->name . '</a>'; //category name & link
$get_children_cats = array(
'child_of' => $catID //get children of this parent using the catID variable from earlier
);
$child_cats = get_categories( $get_children_cats );//get children of parent category
echo '<ul class="children">';
foreach( $child_cats as $child_cat ){
//for each child category, get the ID
$childID = $child_cat->cat_ID;
//for each child category, give us the link and name
echo '<a href=" ' . get_category_link( $childID ) . ' ">' . $child_cat->name . '</a>';
}
echo '</ul></li>';
} //end of categories logic ?>
</ul>
Now this code shows categories and subcategories well but I need to somehow loop through my posts and show them withing categories/subcategories. I have also tried to use fallowing code:
<?php
// get all the categories from the database
$cats = get_categories();
// loop through the categries
foreach ($cats as $cat) {
// setup the cateogory ID
$cat_id= $cat->term_id;
// Make a header for the cateogry
echo "<h2>".$cat->name."</h2>";
// create a custom wordpress query
query_posts("cat=$cat_id&posts_per_page=100");
// start the wordpress loop!
if (have_posts()) : while (have_posts()) : the_post(); ?>
<?php // create our link now that the post is setup ?>
<a href="<?php the_permalink();?>"><?php the_title(); ?></a>
<?php echo '<hr/>'; ?>
<?php endwhile; endif; // done our wordpress loop. Will start again for each category ?>
<?php } // done the foreach statement ?>
</div><!-- #content -->
</div><!-- #container -->
This code shows all categories and posts within particular category, but the structure is not the one I want. I have been trying to combine these two snippets of code for two days, but nothing I try gives me the result I want. I am inexperienced with Wordpress and I could really use help with this.
[
Add and Manage Multilevel Categories in WordPress
WordPress offers categories to help you get up and short out related posts. Visitors can browse through your site content by topics rather than reading post-by-post. Different from tags, categories can be divided by levels, including parent categories and child categories.
In this article, we will dig deep into the reasons why you should create multilevel categories. Then, we will show you how to create and manage parent as well as child categories in WordPress.
Why Creating Multilevel Categories in WordPress
What Are Parent and Child Categories in WordPress?
Categories work as the general topics of your content. Unlike tags that describe specific details of your posts, categories identify what your content is about. If you don’t add categories to a post, it will be assigned the default one namely “Uncategorized” category.
Since categories are hierarchical, you can create sub-categories. Each category can have unlimited child categories. When a post belongs to a child category, you are able to decide if it can be displayed under the parent category archive page.
Here is an example of a main category and its sub-categories. The parent category Private Site has 4 child categories, including Private Categories, Private Custom Post Types, Private Pages, and Private Posts.
Reasons for creating multilevel categories
There are 2 main reasons for adding parent and child categories. The first cause comes to content structure and organization. Multilevel categories also help improve the website SEO effectively.
#1 Improve the user experience
Categories and sub-categories make it easy for users to find content on your site. After reading one post, visitors can land to another related one with ease. This also keeps them staying longer.
#2 Boost the site SEO
Search engines love the category URL structure. When adding a sub-category under the main category, your URL will look something like this: https:mysite.com/main-category/sub-category.
You can use important keywords as categories and sub-categories names. As a result, your content gets ranked on search results pages faster.
2 Ways to Add Parent and Child Categories to WordPress Sites
There are 2 different paths you can take to add categories to your WordPress site, either in the post edit screen or via the Categories page under the Posts section.
#1 Create categories and sub-categories in a post’s edit screen
The following guide shows you how to create the main category and its sub-categories while editing blog posts.
- Go to Posts in your WordPress admin dashboard and choose All Posts
- Select your desired post and click edit
- Look for the Categories section at the right side of the post
- Click the Add New Category link and enter your category name
- Hit Add New Category button at the bottom of the box to save your changes
You can create a new child category in the exact same way as you do for parent categories.
- Click the Add New Category link and enter your sub-category name
- Choose a parent category for it from the Parent Category dropdown
- Save your changes by clicking on Add New Category button
#2 Add multilevel categories in the Categories page
In case you want to create a category before adding content under it, simply
- Go to the Categories page under the Posts section
- Add details of the new category
You should fill in the category name, its slug, and the category description. In case you want to make it the child of another category, pick one from the Parent Category dropdown.
You already have multiple main categories and you want some of them to become sub-categories of one another? For example, we’ve created 5 categories: Private Categories, Private Custom Post Types, Private Pages, Private Posts, and Private Site before. Now, I want the 4 categories Private Categories, Private Custom Post Types, Private Pages, Private Posts to belong to the Private Site category.
Follow these 3 simple steps to add sub-categories to parent categories in the categories page.
- Click on your desired category. In this case, we’ll choose one of the 4 categories mentioned above
- Select its main category from the Parent Category dropdown
- Hit Update at the bottom of the page
The categories Private Categories, Private Custom Post Types, Private Pages, Private Posts from the example appear as child categories of the Private Site category now.
How to Manage Multilevel Categories
There are many things you can do with your WordPress multilevel categories. It’s possible for you to edit, delete, or password protect parent and child-categories.
Edit and deleting a category
You can edit the name, slug or description of a category on the Categories page. All you need to do includes:
- Head to Categories under Posts in your WordPress dashboard
- Hover the category name and click on Quick Edit
- Replace the category name and slug with the new ones
- Simply click Delete when you don’t want that category to exist anymore.
If you want to make further changes, go to the Edit Category page. Besides options like Name, Slug, Parent Category, Description, you’re able to update the metadata for the category. Scroll down to the Yoast SEO section at the bottom of the page and add your focus keyword, title tag, and meta description there.
Please hit Update when you finish all the settings. The Delete option is placed next to the Update button. However, people rarely delete a category permanently. Whenever they don’t want to display a category, they just password protect that category or hide it from the homepage.
Password protect multilevel categories
Apart from standard settings like editing or deleting, you can password protect a private category too. WordPress category should be protected for many reasons. You create premium content for members or paying customers. Once password protected, all posts under a category will be assigned a password automatically. This saves you a lot of time instead of securing individual posts.
Since WordPress doesn’t support locking a category with passwords, you should look for a third-party plugin solution.
Password Protect WordPress Pro allows you to cover the main category as well as its sub-categories under a password form. To install and get started using the plugin, you need to:
- Download PPWP Pro plugin
- Go to Add New under Plugins page
- Click Upload Plugin and select the plugin zip file you’ve downloaded
- Install and activate the plugin
- Visit the Categories page
- Find the category you’d like to protect and click on Protect category link
As a result, the main category Foo Parent and its sub-category Foo A have locked automatically. If you unlock the parent category, the child will become visible to the public too. However, when you make a child category private, its parent won’t be secure.
Make Use of WordPress Multilevel Categories!
Categories and sub-categories help you organize the site content better. They also improve the site SEO thanks to search engine friendly U
RL structures.
It’s simple to create and manage parent and child categories. You can add new categories and sub-categories in both posts’ edit screen and the Categories page.
Not only can you edit and delete the categories but you are also able to password protect multilevel categories. PPWP Pro plugin lets you secure all sub-categories and posts with a password at the same time. You can avoid spending a lot of time protecting single posts.
Still have a question about how to create as well as password protecting multilevel categories? Let us know in the comments below!
CategoriesWordPress Category
Update: Complete code
<ul>
<?php
$get_parent_cats = array(
'parent' => '0' //get top level categories only
);
$all_categories = get_categories( $get_parent_cats );//get parent categories
foreach( $all_categories as $single_category ){
//for each category, get the ID
$catID = $single_category->cat_ID;
echo '<li><a href=" ' . get_category_link( $catID ) . ' ">' . $single_category->name . '</a>'; //category name & link
echo '<ul class="post-title">';
$query = new WP_Query( array( 'cat'=> $catID, 'posts_per_page'=>10 ) );
while( $query->have_posts() ):$query->the_post();
echo '<li><a href="'.get_the_permalink().'">'.get_the_title().'</a></li>';
endwhile;
wp_reset_postdata();
echo '</ul>';
$get_children_cats = array(
'child_of' => $catID //get children of this parent using the catID variable from earlier
);
$child_cats = get_categories( $get_children_cats );//get children of parent category
echo '<ul class="children">';
foreach( $child_cats as $child_cat ){
//for each child category, get the ID
$childID = $child_cat->cat_ID;
//for each child category, give us the link and name
echo '<a href=" ' . get_category_link( $childID ) . ' ">' . $child_cat->name . '</a>';
echo '<ul class="post-title">';
$query = new WP_Query( array( 'cat'=> $childID, 'posts_per_page'=>10 ) );
while( $query->have_posts() ):$query->the_post();
echo '<li><a href="'.get_the_permalink().'">'.get_the_title().'</a></li>';
endwhile;
wp_reset_postdata();
echo '</ul>';
}
echo '</ul></li>';
} //end of categories logic ?>
</ul>
if you want to show the post of parent category and child category in hierarchical form then you
should use the same loop inside parent foreach
loop also use 'cat'=>$catID
incase of parent foreach
loop parent if you want grandchild category and more you need to add more nested foreach
loops and wp_query
If you would like to always show the categories, regardless of if they have posts, you could move the echoing of the $category->name
outside of the if ($posts)
. The way that it is currently, the category name will only be displayed if there is a post assigned with that category.
I think that a potential bigger challenge would be to display the categories in a hierarchy (indenting the sub-categories). If you simply move the display of the category name above the check for posts, they will all show as top-level categories. Here is a discussion of someone working on this issue on Stack Exchange:
https://wordpress.stackexchange.com/questions/270176/showing-categories-and-subcategories-with-posts
I wonder if another possibility would be to use: https://developer.wordpress.org/reference/functions/wp_list_categories/ and then override the HTML generation. It looks like that is what is happening here:
https://wordpress.stackexchange.com/questions/98755/how-can-i-customize-the-wp-list-categories
How to display only posts assigned to a particular, isolated, subcategory
I am trying to set up my wp site where I use posts assigned to categories and subcategories (about 3 levels). I have a list of 1st level categories as my primary menu. When clicked, the intended behavior is to take you to a level 2 subcategory landing page with an Intro post assigned to that subcat and a list of links to the 3rd level sub categories. Upon clicking one of these links, you are taken to the 3rd level category page which displays all of the posts assigned to that 3rd level sub category.
E.g. any_page.php
Primary Menu – Categories: [Cars], Trucks, Trains, Boats
category.php
Level 2 – Cars Category Landing Page: Cars Intro Post (assigned to cars cat) followed by List of Title Links of Cars Subcats:[Ford], Toyota, Nissan, Mitsubishi
category.php
Level 3 – Ford SubCategory Posts Posts assigned to the FORD subcategory: F250, Mustang, Falcon . . .
I have searched the web for weeks, to see how to achieve this, and cant find anything that really does this with posts (not pages). Some articles sort of touch on this but in those examples the links and posts typically are not isolated to the subcategory in which they are linked and you also get the links and posts assigned to the child and/or parent categories/subcategories too.
We can change the default behaviour of including posts attached to child categories by mapping the category_name
query var (set from pretty permalinks) to category__in
(which ignores child categories):
function wpse_184127_ignore_category_children( $wp_query ) {
if ( $wp_query->is_main_query() && $wp_query->is_category() && $name = $wp_query->get( 'category_name' ) ) {
if ( $term = get_term_by( 'slug', sanitize_title_for_query( $name ), 'category' ) ) {
if ( $term->parent )
$depth = count( get_ancestors( $term->term_id, 'category', 'taxonomy' ) );
else
$depth = 0;
if ( $depth <= 1 ) {
$wp_query->set( 'category__in', array( $term->term_id ) );
unset( $wp_query->query_vars['category_name'] );
}
}
}
}
add_action( 'pre_get_posts', 'wpse_184127_ignore_category_children' );
Update: Added depth checking. Just change $depth <= 1
to whichever expression you need. Currently it will only ignore children for top-level and first-level categories (i.e. depth less than or equal to 1).