Wordpress - custom template page for a parent category and all child categories - wordpress

In WP 5.4.2 I want to create a custom archive page for a category and all it's child categories. I am aware of the template file hierarchy:
1. category-slug.php
2. category-ID.php
3. category.php
4. archive.php
5. index.php
but if I understand correctly and if I did all the testing right, the category-slug.php, or the category-id.php scheme applies to a single category regardless of the category hierarchy.
Let's say I have following categories:
colors (id 2)
- red (id 10)
- green (id 11)
- blue (id 12)
I need a single template file for all of them. Simply creating category-colors.php or category-2.php doesn't work. It applies to the single category (colors) only. I want it to apply to all the current child categories, as well as all the child categories I add in the future. Is it possible? If so, please advice how.

There are a couple of ways to do this, but using the category_template filter to let you use a custom category template seems the most common.
The function below will let you dynamically check back through the parent levels of the current category until it finds a template called "category-[parent slug]" for the closest ancestor category or it reaches the top level - whichever is first.
Suppose you have something like:
- products
- hardware
- food
- dairy
- vegetables
On the dairy page, it will first check if you have a slug called category-dairy.php.
If you do, it will return it.
If you don't, it will look for category-food.php.
If that's not found, it will look for category-products.php.
Add this to your functions.php - this is untested by the code is well commented so you can understand how it works:
function get_template_for_category( $template ) {
if ( basename( $template ) === 'category.php' ) { // No custom template for this specific term, let's find it's parent
// get the current term, e.g. red
$term = get_queried_object();
// check for template file for the page category
$slug_template = locate_template( "category-{$term->slug}.php" );
if ( $slug_template ) return $slug_template;
// if the page category doesn't have a template, then start checking back through the parent levels to find a template for a parent slug
$term_to_check = $term;
while ( $term_to_check ->parent ) {
// get the parent of the this level's parent
$term_to_check = get_category( $term_to_check->parent );
if ( ! $term_to_check || is_wp_error( $term_to_check ) )
break; // No valid parent found
// Use locate_template to check if a template exists for this categories slug
$slug_template = locate_template( "category-{$term_to_check->slug}.php" );
// if we find a template then return it. Otherwise the loop will check for this level's parent
if ( $slug_template ) return $slug_template;
}
}
return $template;
}
add_filter( 'category_template', 'get_template_for_category' );
References:
WP Codex category_template Reference
WP Developer locate_template Reference
Make categories use parent template

Related

Woocommerce choose grid or list view for each category

I want the possibility to choose between grid and list view for each Woocommerce category. I have found this plugin: https://nl.wordpress.org/plugins/woocommerce-grid-list-toggle/
However, the plugin is meant for the shopper to choose whether to display items in grid view or list view. What I truly want is the ability to assign a view for each category in the back-end.
Example:
Category A is displayed as grid
Category B is displayed as list
Breaking my head over this.
Similar to this question you need to filter template_include. You need to call your custom archive template archive-list-view.php and save it in your theme's woocommerce folder. Obviously, you can name it anything you like, you will just have to adjust the code below to match.
Folder structure:
/theme-folder/functions.php
/theme-folder/woocommerce/archive-list-view.php
On the template_include filter we will check if we are on the term archive for the nussmylch product category. If so, we'll look for and supply the new template. Otherwise, the standard template is used.
EDIT: incorrect WooCommerce function is_product_taxonomy() was used. is_product_category() is needed to check for a specific category.
add_filter( 'template_include', 'so_33615903_custom_category_template', 20 );
function so_33615903_custom_category_template( $template ) {
// check you are on the taxonomy archive for specific category
if ( is_product_category( 'nussmylch' ) ) {
$new_template = locate_template( array( 'woocommerce/archive-list-view.php' ) );
if ( '' != $new_template ) {
$template = $new_template ;
}
}
return $template;
}
Working Example

Replacing only parts of an archive and single page template of WordPress

I am having a bit of trouble here understanding how to do the following. I have searched for weeks now but cannot seem to find what I am looking for.
I have a custom post type 'product' and want to change which template gets loaded for the single product page as well as the archive for the products. I am using the following code to load include and load templates.
add_filter('template_include', function() {
if (is_post_type_archive('product')) {
$templatefilename = 'archive-product.php';
$template = WPVS_PATH . 'templates/' . $templatefilename;
return $template;
}
if ('product' == get_post_type() ){
$templatefilename = 'single-product.php';
$template = WPVS_PATH . 'templates/' . $templatefilename;
return $template;
}
});
The problem I am having is that it replaces the current theme's template instead of just the inner part of the content and archive areas.
Here is what I want to achieve:
Create a custom post type 'product' in a plugin - DONE (Was kinda easy!)
When opening a single product only change the content part. - I can do this with the_content filter hook. Simple enough. Any other suggestions is welcome.
When I go to the archive view for the 'product' custom post type I don't want to have it load the theme's default archive (list) view but instead a grid view from my plugin which I cannot seem to get right. I only want to change the inner part of the template, not the whole page.
I have created this plugin a few weeks ago using only shortcodes which works good but want to see if I can do it without the use of shortcodes by means of creating the custom post type and changing the inner template parts of the current active theme.
Can anybody steer me into the right direction here?
If I create a theme I can do what I am looking for but I want to create this into a plugin instead without adding or making changes to the active theme. The plugin should handle what is needed.
The same issue is discussed here but what I want is to develop something that is theme independent. No changes should be made in theme files and no theme files should be copied to the plugin.
WP - Use file in plugin directory as custom Page Template?
Recently I also had the same problem. Here's how I worked it out.
template_include filter accepts a parameter which is the selected template that you want to override (this what you are missing in your code).
I don't know but sometimes the filter hook need higher priority to work like 9999. But first check if it work with default priority, if don't change it.
I assume your both archive and single product template both have include get_header() and get_footer() which can be used for default selected theme (Or if the theme has different setup, setup accordingly).
This is simplified code:
add_filter('template_include', function($default_template) {
if (is_post_type_archive('product')) {
$templatefilename = 'archive-product.php';
$template = WPVS_PATH . 'templates/' . $templatefilename;
$default_template = $template;
} else if ('product' == get_post_type() ) {
$templatefilename = 'single-product.php';
$template = WPVS_PATH . 'templates/' . $templatefilename;
$default_template = $template;
}
// Load new template also fallback if both condition fails load default
return $default_template;
}, 9999); // set priority, only if not worked with default one
The best option in this case is to provide a shortcode to the user. So they can place it on any page that they want (or that you auto generate). That way you will place your content inside their theme.
Something like this:
add_shortcode( 'slotsl-game', 'embed_game' );
/**
* Print the game
* #return false|string
*/
function embed_game(){
ob_start();
$game = get_post();
include_once SLOTSL_PLUGIN_DIR . 'templates/slotsl-single-game.php';
return ob_get_clean();
}

How to get parent category and child category go to different pages, or display different formats

I am currently trying to do a directory style site, and I currently have parent categories and child categories. Right now I have the parent categories showing and when you click on the parent it shows the child categories. Problem is now, I can't figure out how to display all the material in the child categories when you click on the child categories. Is there a conditional statement or a way that I can have the child categories go to the archive.php so it can display something else. Right now parent and the child categories pull from the category.php, so they end up being the same page.
I ended up figuring it out. I did the following:
In functions.php create function:
function is_subcategory (){
$cat = get_query_var('cat');
$category = get_category($cat);
$category->parent;
return ( $category->parent == '0' ) ? false : true;
}
Then in the category.php I did:
if ( is_subcategory() ) {
// do required actions
}

Wordpress latest posts menu item

I'm trying to get Wordpress to give me a menu item to go to "latest posts." They come up on the frontpage, but once I navigate away, I want a menu item to get back there. It seems so obvious, but several hours later, the best I could do was create a custom menu with a link to "uncategorised" as a workaround. There MUST be a better way! And this way, I get a box saying "Archive of posts filed under the Uncategorized category. " Not wanted!
Create a custom page in your template directory (http://codex.wordpress.org/Pages#Page_Templates) with a custom query (check at http://codex.wordpress.org/Class_Reference/WP_Query, http://codex.wordpress.org/Function_Reference/query_posts or http://codex.wordpress.org/Template_Tags/get_posts).
Create a page in your admin and select the template you created.
Add a link to this page in your menu and you're done.
Maybe this will help: http://www.viper007bond.com/2011/09/20/code-snippet-add-a-link-to-latest-post-to-wordpress-nav-menu/
It's a filter that will 'search and replace' placeholder anchors such as '#latestpost1' with the actual url of the latest post, and thus dynamically modify the menu before it's rendered.
I'm not sure how this is for SEO, but it's a clever solution.
Give all your posts a category name. Use something generic like "News", "Articles" or "Blogs". Then, choose the category with the name you picked from the menu page under categories. Add this category link to your menu. Rename the link whatever you wish - "Blog" - for example. And, viola - all your posts will appear when people click on that link.
Try this plugin: https://de.wordpress.org/plugins/dynamic-latest-post-in-nav-menu/ works really well and code is open sourced here: https://github.com/hijiriworld/dynamic-latest-post-in-nav-menu
simple solution:
I took this guy's code: http://www.viper007bond.com/2011/09/20/code-snippet-add-a-link-to-latest-post-to-wordpress-nav-menu/
Basically what he wrote is for the menu item to link to the latest post, not posts (plural), so I just modified it and it's working:
<?php
if ( ! is_admin() ) {
// Hook in early to modify the menu
// This is before the CSS "selected" classes are calculated
add_filter( 'wp_get_nav_menu_items', 'replace_placeholder_nav_menu_item_with_latest_post', 10, 3 );
}
// Replaces a custom URL placeholder with the URL to the latest post
function replace_placeholder_nav_menu_item_with_latest_post( $items, $menu, $args ) {
// Loop through the menu items looking for placeholder(s)
foreach ( $items as $item ) {
// Is this the placeholder we're looking for?
if (!strpos(($item->url), 'latestpost'))
continue;
// if ( 'latestpost' != $item->url )
// continue;
// Get the latest post
$latestpost = get_posts( array(
'numberposts' => 1,
) );
if ( empty( $latestpost ) )
continue;
// Replace the placeholder with the real URL
$new_link = $item->url;
$new_link = substr($new_link, 0, strlen($new_link) - 12);
$item->url = $new_link;
}
// Return the modified (or maybe unmodified) menu items array
return $items;
}

Can I hide a Category (and its subcategories) from the sidebar?

I put the widget category on the primary sidebar, from the dashboard. Than, on code, I use :
<?php get_sidebar('left'); ?>
and it create the code for the categories. Now, I'd like to hide the category with tag_ID=6, and all of its subcategories.
How can I do it?
Tried this tutorial, but seems that I don't have the $cat_args = "orderby=name&show_count={$c}&hierarchical={$h}"; line? I'm on last version of WordPress, 3.4.2
The tutorial seems outdated, so I wouldn't rely on that. It is not necessary to hack around in the WordPress-source - create a simple Plugin which hooks into the right filters.
In your case those filters are widget_categories_dropdown_args (when you select "Display as dropdown" in the Widget-options) and widget_categories_args (if the Widgets displays the list as normal text with links).
With that knowledge you can now code the actual plugin (I've called it Myplugin, I think you should rename it) - just put that PHP code into the file wp-content/plugins/myplugin.php:
<?php
/**
* #package Myplugin
* #version 1.0
*/
/*
Plugin Name: Myplugin
Plugin URI: http://example.com
Description:
Author: You
Version: 1.0
Author URI: http://example.com
*/
// Create a list with the ID's of all children for
// the given category-id
function myplugin_recursive_filter($catid) {
$result = array($catid);
$cats = get_categories(array(
'child_of' => $catid,
));
foreach($cats as $category) {
$result[] = $category->cat_ID;
}
return implode(",", $result);
}
// Actual filter function. Just set the "exclude"
// entry to a comma separated list of category ID's
// to hide.
function myplugin_filter_categories_args($args) {
// 6 is the "tag_ID"
$args['exclude'] = myplugin_recursive_filter(6);
// or hard code the list like that:
//$args['exclude'] = '6,10,11,12';
// but you'd have to include the ID's of the
// children, because "eclude" is not recursive.
return $args;
}
// Register the filter to the relevant tags
add_filter('widget_categories_dropdown_args',
'myplugin_filter_categories_args', 10, 1);
add_filter('widget_categories_args',
'myplugin_filter_categories_args', 10, 1);
The function myplugin_recursive_filter is necessary, because the exclude-entry is not recursive (except if you check "Show hierarchy" in the widget options). If your categories don't change that much you could replace function call with a hard-coded list of ID's (with the children) for better performance.

Resources