I am trying to get the woocommerce subcategories with products to show under the main categories.
<ul class="wsubcategs">
<?php
$wsubargs = array(
'hierarchical' => 1,
'show_option_none' => '',
'hide_empty' => 0,
'parent' => $category->term_id,
'taxonomy' => 'product_cat'
);
$wsubcats = get_categories($wsubargs);
foreach ($wsubcats as $wsc):
?>
<li><?php echo $wsc->name;?>
</li>
<?php
endforeach;
?>
</ul>
So far this has gotten me the corrent subcategories under the correct main categories, but no products are being shown under them.
Any advice would be appreciated.
O.
There are many ways to do this in Wordpress. You could do a custom query using the WP_Query object to get all of the products in that category, which would be the most flexible option, but there is an easier way.
Woocommerce provides shortcodes specifically for showing products in a specific category. The output would use the templates that are already built in to Woocommerce.
<?php echo do_shortcode('[product_category category="appliances"]');?>
This will give you the products under a specific category.
In your code, you might do something like this:
<ul class="wsubcategs">
<?php
$wsubargs = array(
'hierarchical' => 1,
'show_option_none' => '',
'hide_empty' => 0,
'parent' => $category->term_id,
'taxonomy' => 'product_cat'
);
$wsubcats = get_categories($wsubargs);
foreach ($wsubcats as $wsc):
?>
<li>
<?php echo $wsc->name;?>
<div class="products">
<?php echo do_shortcode('[product_category category="'.$wsc->slug.'"]');?>
</div>
</li>
<?php endforeach;?>
</ul>
I noticed in your question that you're outputting a list. It seems likely to me that you wouldn't want to actually output the products (detailed template) below each of the categories, but you might rather want to show the number of products or product titles in a sublist.
Here's how you would show the number of products:
count;?>
You would use this anywhere in the foreach loop you have above.
Here's how you would show a sublist of titles of products in the list element for each category:
<?php $subcategory_products = new WP_Query( array( 'post_type' => 'product', 'product_cat' => $wsc->slug ) );
if($subcategory_products->have_posts()):?>
<ul class="subcat-products">
<?php while ( $subcategory_products->have_posts() ) : $subcategory_products->the_post(); ?>
<li>
<a href="<?php echo get_permalink( $subcategory_products->post->ID ) ?>">
<?php the_title(); ?>
</a>
</li>
<?php endwhile;?>
</ul>
<?php endif; wp_reset_query(); // Remember to reset ?>
And here's how that would look in your code above:
<ul class="wsubcategs">
<?php
$wsubargs = array(
'hierarchical' => 1,
'show_option_none' => '',
'hide_empty' => 0,
'parent' => $category->term_id,
'taxonomy' => 'product_cat'
);
$wsubcats = get_categories($wsubargs);
foreach ($wsubcats as $wsc):
?>
<li>
<?php echo $wsc->name;?>
<?php $subcategory_products = new WP_Query( array( 'post_type' => 'product', 'product_cat' => $wsc->slug ) );
if($subcategory_products->have_posts()):?>
<ul class="subcat-products">
<?php while ( $subcategory_products->have_posts() ) : $subcategory_products->the_post(); ?>
<li>
<a href="<?php echo get_permalink( $subcategory_products->post->ID ) ?>">
<?php the_title(); ?>
</a>
</li>
<?php endwhile;?>
</ul>
<?php endif; wp_reset_query(); // Remember to reset ?>
</li>
<?php endforeach;?>
</ul>
**Show Category and Sub Category in search Box**
----------
<?php
//template name:house
?>
<style>
.abc {
margin-left: 10px;
}
</style>
<?php
$taxonomy = 'product_cat';
$orderby = 'name';
$show_count = 0; // 1 for yes, 0 for no
$pad_counts = 0; // 1 for yes, 0 for no
$hierarchical = 1; // 1 for yes, 0 for no
$title = '';
$empty = 0;
$args = array(
'taxonomy' => $taxonomy,
'orderby' => $orderby,
'show_count' => $show_count,
'pad_counts' => $pad_counts,
'hierarchical' => $hierarchical,
'title_li' => $title,
'hide_empty' => $empty
);
?>
<select>
<?php
$all_categories = get_categories( $args );
foreach ($all_categories as $cat)
{
if($cat->category_parent == 0)
{
$category_id = $cat->term_id;
$thumbnail_id = get_woocommerce_term_meta( $cat->term_id, 'thumbnail_id', true );
$image = wp_get_attachment_url( $thumbnail_id );
$abc=$cat->name;
if($abc=="") {
?>
<option value="<?php echo $cat->slug;?>"><?php echo $abc; ?></option>
<?php }
$args2 = array(
'taxonomy' => $taxonomy,
'child_of' => 0,
'parent' => $category_id,
'orderby' => $orderby,
'show_count' => $show_count,
'pad_counts' => $pad_counts,
'hierarchical' => $hierarchical,
'title_li' => $title,
'hide_empty' => $empty
);
$sub_cats = get_categories( $args2 );
if($sub_cats)
{
foreach($sub_cats as $sub_category)
{
?>
<?php
if($sub_cats->$sub_category == 0)
{
$suv= $sub_category->cat_name;?>
<option class="abc" value="<?php echo $sub_category->slug; ?>"><span class="abc"><?php echo $suv; ?></span></option>
<?php } } } } } ?>
</select>
Related
I've written this function which nearly works:
function all_animals() {
$categories = get_categories(array(
'echo' => 0,
'hide_empty' => 0,
'taxonomy' => 'species',
'hierarchical' => 1,
'show_count' => 0,
'depth' => 0
)); ?>
<ul>
<?php ob_start();
foreach ($categories as $cat) {
$cat_args = array(
'posts_per_page' => -1,
'post_type' => 'animal',
'showposts' => -1,
'post_status' => 'publish',
'cat' => $cat->cat_ID
);
$the_animals = new WP_Query($cat_args);
$animal_count = $the_animals->post_count;
?>
<li>
<a href="<?php echo get_category_link( $cat->cat_ID ); ?>">
<?php echo $cat->cat_name; ?>
<span class="count"><?php echo $animal_count; ?></span>
</a>
</li>
<?php
}
wp_reset_postdata();
$animal_list = ob_get_clean();
return $animal_list;
echo '</ul>';
}
...and then I use it on a page template like this:
echo all_animals();
The problem: The only thing not working is the $animal_count which always returns a 0.
I have also tried this...
global $wp_query;
$animal_count = $wp_query->found_posts;
...but that made no difference.
How can I fix this?
You can use this
get_category('ID')->category_count
Here 'ID is category id
The solution was easier than I thought:
$animal_count = $the_animals->count;
EDIT: After changing the tax_query to slug it now outputs posts in the first loop (the first cat) but does not in the next tab/cat which I know has many published posts assigned to it.
I created a shortcode that is meant to grab all the categories in a CPT and out them into bootstrap tabs with a certain amount of posts per tab.
To do this I do get_categories for the tabs nav (Works fine).
Then I do get_categories again to output the tabs content (Also works fine) with a wp_query inside each where I grab the posts. This is what is not working. No output.
If I echo the category name or any data I can grab from the get_categories it echo's it. So it seems the issue is with the WP_Query.
Here is the code:
add_shortcode( 'tabbed_grid_articles', 'tabbed_grid_articles' );
function tabbed_grid_articles($args = array()){
global $post;
$current_id = $post->ID;
$defaults = apply_filters( 'dy_tabbed_grid_default_args', array(
'posts_per_page' => 1,
'orderby' => 'date',
'order' => 'DESC',
'echo' => true,
'post_type' => 'playbooks',
'category' => 0,
'hide_empty' => true,
'exclude' => '',
'include' => '',
'taxonomy' => 'playbooks_category',
));
$args = wp_parse_args( $args, $defaults );
$cat_args = array(
'taxonomy' => $args['taxonomy'],
'orderby' => 'menu_order',
'order' => 'ASC',
'hierarchical' => true,
'parent' => $args['category'],
'hide_empty' => $args['hide_empty'],
'child_of' => $args['category'],
'exclude' => $args['exclude'],
'include' => $args['include']
);
$categories = get_categories($cat_args);
?> <ul class="nav nav-tabs" role="tablist"> <?php
$count = 0;
foreach($categories as $category){
$targetID = str_replace(' ', '-', $category->cat_name);
?> <!-- Nav tabs -->
<li role="presentation" class="<?php if($count == 0){echo 'active'; $count ++;} ?>"><?php echo $category->cat_name ?></li>
<?php
}
// wp_reset_postdata();
?> </ul>
<!-- Tab panes -->
<div class="tab-content">
<?php
$count = 0;
foreach($categories as $category) {
$targetID = str_replace(' ', '-', $category->cat_name);
$args['tax_query'] = array(array(
'taxonomy' => $args['taxonomy'],
'field' => 'slug',
'terms' => $category->cat_name,
),
);
// $args['cat'] = $category->cat_ID;
$grid_query = new WP_Query($args);
?>
<div role="tabpanel" class="tab-pane <?php if($count == 0){echo 'active'; $count ++;} ?>" id="tab-<?php echo $targetID ?>">
<?php
if($grid_query->have_posts()) {
while ($grid_query->have_posts()) {
$grid_query->the_post();
echo get_the_title();
//echo '1<br>';
//echo $args['cat'];
//echo $category->cat_name;
//echo get_the_excerpt();
echo '<br>';
//the_excerpt();
}
wp_reset_postdata();
}
?></div>
<?php
}
?>
</div>
<?php
}
I tried $args['cat'] = $category->cat_ID; instead of tax_query but neither work.
If I comment them both out then I get all the posts from the cpt. Currently just echoing the excerpt...
Any ideas?
Solved. I took for granted that the slug was the same as the name and it was not.
I think I only changed the slug to be the name by mistake when debugging at first when it was not working. Anyway, changed 'terms' => $category->cat_name, to 'terms' => $category->slug, and it worked.
Hope this helps someone in the future.
I have a Wordpress (version 4.2.2) eCommerce site running WooCommerce (version 2.3.8).
On my individual product page I wish to set the title of the product to also include the custom categories I have created in WooCommerce and that this product belongs to.
I find the following file (wp-content/themes/mytheme/woocommerce/single-product/title.php) that relates to the title of the individual product and edit it as below to try and include the categories that this product belongs to in the title as well.
With the code below I manage to display the categories, but the problem is that I am displaying ALL categories, and not just the categories that this product belongs to.
How do I limit the categories returned to only the categories that the product belongs to please?
<?php
if ( ! defined( 'ABSPATH' ) )
exit; // Exit if accessed directly
?>
<!-- Original Product Title START -->
<h1 itemprop="name" class="product-title entry-title">
<?php the_title(); ?>
</h1>
<!-- Original Product Title END -->
<!-- New Product Title START -->
<h1 itemprop="name" class="product-title entry-title">
<?php
$taxonomy = 'product_cat';
$orderby = 'name';
$show_count = 0; // 1 for yes, 0 for no
$pad_counts = 0; // 1 for yes, 0 for no
$hierarchical = 1; // 1 for yes, 0 for no
$title = '';
$empty = 0;
$args = array(
'taxonomy' => $taxonomy,
'orderby' => $orderby,
'show_count' => $show_count,
'pad_counts' => $pad_counts,
'hierarchical' => $hierarchical,
'title_li' => $title,
'hide_empty' => $empty
);
?>
<?php
$all_categories = get_categories( $args );
foreach ($all_categories as $cat)
{
if($cat->category_parent == 0)
{
$category_id = $cat->term_id;
?>
<?php
echo '<br />'. $cat->name .'';
?>
<?php
$args2 = array(
'taxonomy' => $taxonomy,
'child_of' => 0,
'parent' => $category_id,
'orderby' => $orderby,
'show_count' => $show_count,
'pad_counts' => $pad_counts,
'hierarchical' => $hierarchical,
'title_li' => $title,
'hide_empty' => $empty
);
$sub_cats = get_categories( $args2 );
if($sub_cats)
{
foreach($sub_cats as $sub_category)
{
echo '<br/>'. $sub_category->name .'';
echo apply_filters( 'woocommerce_subcategory_count_html', ' <span class="cat-count">' . $sub_category->count . '</span>', $category );
}
}
?>
<?php
}
}
?>
</h1>
<!-- New Product Title END -->
you can simply get all the categories assign to product by using get_the_terms
$terms = get_the_terms( get_the_ID(), 'product_cat' );
foreach ($terms as $term) {
echo '<h1 itemprop="name" class="product-title entry-title">'.$term->name.'</h1>';
}
Use the get_categories function to retrieve categories name :-
You can use this code to display product categories name -
<?php global $post, $product;
$categ = $product->get_categories();
echo $categ; ?>
I have a categories page template, listing all categories with featured images. But I want to show only subcategories of a parent category. I don't know where to modify the template. Here is the code.
get_header(); ?>
<?php if(have_posts()) : ?><?php while(have_posts()) : the_post(); ?>
<h1 class="border-radius-5"><?php the_title(); ?></h1>
<div id="page" class="post-content">
<?php the_content(); ?>
<?php
$terms = get_terms("category", $args);
$count = count($terms);
$categories = array();
if ($count > 0) {
echo '<ul class="listing-cat">';
foreach ($terms as $term) {
$args = array(
'post_type' => 'post',
'posts_per_page' => 1,
'show_count' => 1,
'orderby' => 'rand',
'post_status' => 'publish',
'tax_query' => array(
array(
'taxonomy' => 'category',
'field' => 'slug',
'terms' => $term->slug
)
)
);
$video_from_categorie = new WP_Query( $args );
if( $video_from_categorie->have_posts() ){
$video_from_categorie->the_post();
}else{}
$term->slug;
$term->name;
?>
<li class="border-radius-5 box-shadow">
<?php echo get_post_image();?>
<span><?php echo $term->name; ?></span>
<span class="nb_cat border-radius-5"><?php echo $term->count; ?> <?php if ( $term->count > 1 ){
_e( 'videos', get_theme_name() );
}else{
_e( 'video', get_theme_name() );
} ?></span>
</li>
<?php
}
echo '</ul>';
echo '<div class="clear"></div>';
}
?>
</div><!-- #page -->
<?php endwhile; ?>
<?php endif; ?>
Pass the ID of the desired parent term/category to the child_of parameter of get_terms():
$terms = get_terms( 'category', array( 'child_of' => TERM_ID_GOES_HERE ) );
I am building a custom sitemap for a website I am working on, the only way I've managed to apply my custom filters and display the proper pages is to create several loops that check each time if the parent has children, then displays them accordingly. This is a fairly large site and has a ton of content.
This is my current loop which draws out each page title and link:
<?php $children = get_posts( array('category' => $region_id, 'post_type' => 'page', 'numberposts' => 100, 'post_parent' => $pg->ID, 'post_status' => 'publish', 'orderby' => 'menu_order', 'order' => 'ASC') ); ?>
<?php if ($children) : ?>
<ul class="children">
<?php foreach ($children as $child) : ?>
<?php $subkids = get_posts( array('category' => $region_id, 'post_type' => 'page', 'numberposts' => 100, 'post_parent' => $child->ID, 'post_status' => 'publish', 'orderby' => 'menu_order', 'order' => 'ASC') ); ?>
<li>
<?php echo $child->post_title;?>
<?php if( count( $subkids ) != 0 ) : ?>
<ul class="children">
<?php foreach($subkids as $kid) : ?>
<?php $subkids2 = get_posts( array('category' => $region_id, 'post_type' => 'page', 'numberposts' => 100, 'post_parent' => $kid->ID, 'post_status' => 'publish', 'orderby' => 'menu_order', 'order' => 'ASC') ); ?>
<li>
<?php echo $kid->post_title; ?>
<?php if( count( $subkids2 ) != 0 ) : ?>
<ul class="children">
<?php foreach($subkids2 as $kid2) : ?>
<?php $subkids3 = get_posts( array('category' => $region_id, 'post_type' => 'page', 'numberposts' => 100, 'post_parent' => $kid2->ID, 'post_status' => 'publish', 'orderby' => 'menu_order', 'order' => 'ASC') ); ?>
<li>
<?php echo $kid2->post_title; ?>
<?php if( count( $subkids3 ) != 0 ) : ?>
<ul class="children">
<?php foreach($subkids3 as $kid3) : ?>
<li>
<?php echo $kid3->post_title; ?>
</li>
<?php endforeach; ?>
</ul>
<?php endif; //for if forth level children exist ($subkid3) ?>
</li>
<?php endforeach; ?>
</ul>
<?php endif; //for if third level children exist ($subkid2) ?>
</li>
<?php endforeach; ?>
</ul>
<?php endif; //for if second level children exist ($subkids) ?>
</li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
Edit: I removed my custom meta filters from the code to reduce space, but here is an example of what I apply inside each loop:
<?php $meta = get_post_meta($child -> ID, 'wpcf-visible-in-sitemap'); ?>
<?php if($meta[0] != 1) : // If page should not be displayed, hide it ?>
<li><?php echo get_the_title($child -> ID); ?></li>
<?php endif; ?>
This is really nasty looking, is there a more efficient way of coding this?
Recursive functions have resolved my issue, I was able to reduce the code to the following:
function check_for_children( $region_id, $children ) {
if ( count($children) > 0 ) {
echo '<ul class="children">';
foreach($children as $child) {
echo '<li>' . $child -> post_title . '</li>';
$children = get_posts( array('category' => $region_id, 'post_type' => 'page', 'numberposts' => 100, 'post_parent' => $child -> ID, 'post_status' => 'publish', 'orderby' => 'menu_order', 'order' => 'ASC') );
check_for_children($region_id, $children);
}
echo '</ul>';
} else {
return;
}
}
The function calls itself until there are no longer and children, at which point it moves along to the next set.