I want to get all categories in wordpress site but separately parent and child categories(in such way it's easily for me to style). In the following code I get parent categories but all children categories are repeated for every parent.
Thanks!
<?php
$args = array(
'orderby' => 'name',
'parent' => 0
);
$categories = get_categories( $args );
$categories_sub = get_categories();
foreach ( $categories as $category ) {
echo '<ul class=" span-5 colborder list_main "> ' . $category->name . '<br/>';
foreach ( $cat->parent > 1 and $categories_sub as $cat) {
$temp=$category->name + '/';
if(get_category_parents($cat)==$temp) {
echo '' . $cat->name . '<br/>';
}
$temp="";
}
echo '</ul>';
}
?>
There are several ways to create HTML list of categories.
wp_list_categories()
Default CSS selectors
Simplest way is to display a list of categories with wp_list_categories() and style the output with default CSS selectors:
li.categories
li.cat-item
li.cat-item-7
li.current-cat
li.current-cat-parent
ul.children
The Walker_Category class
The Walker class is for traversing the hierarchical data like menus or categories. It is an abstract class that has four abstract methods start_el(), end_el(), start_lvl(), end_lvl(). It is not required to override all abstract methods of the class, only those methods that are needed.
$args = array( 'hide_empty' => false, 'walker' => new MyWalker(), 'title_li' => false );
wp_list_categories( $args );
class MyWalker extends Walker_Category {
function start_el( &$output, $category, $depth = 0, $args = array(), $id = 0 ) {
$output .= '<a href="' . get_category_link( $category->term_id ) . '" >' . $category->name . '</a><br/>';
}
function end_el( &$output, $page, $depth = 0, $args = array() ) {}
function start_lvl( &$output, $depth = 0, $args = array() ) {
$output .= '<ul class="span-5 colborder list_main">'.PHP_EOL;
}
function end_lvl( &$output, $depth = 0, $args = array() ) {
$output .= '</ul>'.PHP_EOL;
}
}
Recursive Function
Recursive Function is also a good way to traverse through categories. This way you have to manually get the categories on each node. Since the get_categories() function returns all the children categories in all subnodes, id of the current category must be passed on to be able to display only the current level categories.
get_the_categories();
function get_the_categories( $parent = 0 )
{
$categories = get_categories( "hide_empty=0&parent=$parent" );
if ( $categories ) {
echo '<ul class="span-5 colborder list_main">';
foreach ( $categories as $cat ) {
if ( $cat->category_parent == $parent ) {
echo '<a href="' . get_category_link( $cat->term_id ) . '" >' . $cat->name . '</a><br/>';
get_the_categories( $cat->term_id );
}
}
echo '</ul>';
}
}
i had implemented this code a while ago but you can give it a try..
// get_categories() function will return all the categories
$upaae_categories = get_categories( array(
'orderby' => 'name',
'order' => 'ASC'
) );
foreach( $upaae_categories as $single_cat ) {
if($single_cat->parent < 1) // Display if parent category and exclude child categories
{
echo 'Parent: '.$single_cat->name;
// now get all the child categories
$child_categories=get_categories(
array( 'parent' => $single_cat->term_id )
);
if(sizeof($child_categories)>0){ /* this is just for ensuring that this parent category do have child categories otherwise a category cannot be a parent if does not have any child categories*/
echo '###childs###</br>'
foreach ($child_categories as $child) {
echo $child->name.'</br>';
}// end of loop displaying child categories
} //end of if parent have child categories
}
}
Related
I Write a Custom Nav Walker in My Wordpress Custom Child Theme.
I Need To Detect Current Category in my end_lvl Function. Is there Any Solution ?
function end_lvl(&$output, $depth=0, $args=null) {
$indent = str_repeat( "\t", $depth );
$divder_div_start = "<div class=\"megamenu-divder\">";
$divder_div_end = "</div>";
// Get 4 most recent product IDs in date descending order.
$query = new WC_Product_Query( array(
'limit' => 4,
'orderby' => 'date',
'order' => 'DESC',
'return' => 'ids',
'category' => array( 'md-o-poshak' ),
) );
$topseller_img_tags = '';
$products = $query->get_products();
foreach($products as $p_id){
$image = wp_get_attachment_image_src( get_post_thumbnail_id( $p_id ));
$topseller_img_tags .= "\n<div><img src='$image[0]' width='150' height='150' /></div>";
}
$topseller_div_start = "<div class=\"top-seller-megamenu\">";
$topseller_div_end = "</div>";
if($depth > 0)
{
$output .= "$indent</ul>\n$indent\n$divder_div_start\n$divder_div_end\n$topseller_div_start\n$topseller_img_tags\n$topseller_div_end\n</section>\n";
}
else
{
$output .= "</ul>";
}
}
i need category name.
try to add this:
$cat_name = '';
if (is_category()) {
$category = get_queried_object();
$cat_name = $category->name;
}
I've put together a custom filter sidebar for my WooCommerce Category page.
Some info about the sidebar:
It pulls in all active product categories, allowing flexibility for the client to add more down the road.
Each item clicks through to its appropriate category page.
One parent category is hidden from the loop (id 122).
The initial loop calls in parent categories
The sub loop pulls in child categories (If there are any & if they have products).
I'm using $product_cat to identify if the current category page is the same as the cat in the sidebar, allowing a class to be added so it can be highlighted when on the page.
Q
Much like with what I've done with $product_cat, I would like to be able to identify within the loop IF the parent category on the sidebar is the parent of the child category page the user is currently on. With this in place, I can then add a class to the parent category li.
I've spent some time crawling the website in an attempt to find a solution but sadly not.
My full code below:
global $wp_query;
$cat_name = "product_cat";
$parent_cat_terms = get_terms($cat_name, array('parent' => 0, 'orderby' => 'slug', 'hide_empty' => true, 'exclude' => 122 ));
// IF Current declaration
global $wp_query;
$product_cat = $wp_query->query_vars['product_cat'];
echo '<ul class="cat-filters">';
foreach ($parent_cat_terms as $parent_term) {
if( $parent_term->count > 0 ):
echo '<li class="cat-parent';
if( $parent_term->slug == $product_cat ){
echo ' class="page-cat"';
}
echo '"><a href="' . get_term_link($parent_term) . '"';
if (strpos($parent_term->slug, $product_cat ) !== false) {
echo ' class="page-cat"';
}
echo'>' . $parent_term->name . '</a>';
$child_cat_terms = get_terms($cat_name, array('parent' => $parent_term->term_id, 'orderby' => 'slug', 'hide_empty' => true));
if ( !empty( $child_cat_terms ) && !is_wp_error( $child_cat_terms ) ){
echo '<ul class="cat-child">';
foreach ($child_cat_terms as $child_term) {
if( $child_term->count > 0 ):
echo '<li><a href="' . get_term_link($child_term) . '"';
if( $child_term->slug == $product_cat ){
echo ' class="page-cat"';
}
echo'>' . $child_term->name . '</a></li>';
endif;
}
echo "</ul>";
}
echo '</li>';
endif;
}
echo '</ul>';
I have the WP Jb manager plugin which I believe is just a custom post type for jobs. I have enabled categories created some categories.
I need to just show the children of each category instead of the whole list of categories.
I have the following code:
<?php
$terms = get_terms( 'job_listing_category', 'orderby=count&hide_empty=0' );
$count = count($terms);
if ( $count > 0 ){
echo "<ul>";
foreach ( $terms as $term ) {
echo "<li>" . $term->name . "</li>";
}
echo "</ul>";
}
?>
Which outputs a list of all categories (parent and children) as so:
Office
Warehouse
Manufacturing
Industrial
Construction
Building Services Engineers
The parent categories are the bold ones: Office, Industrial and Construction. I want to take one of them and display the children of that category only.
For example: get_category('industrial', 'children_of') (I know that's not the correct syntax), so it would result in showing the children only of the industrial category:
Warehouse
Manufacturing
I can't seem to find a way to do this - Could anyone help?
I managed to do this by using the following code:
<?php
$terms = get_terms( 'job_listing_category', 'parent=59' );
$count = count($terms);
if ( $count > 0 ){
echo "<ul>";
foreach ( $terms as $term ) {
echo "<li>" . $term->name . "</li>";
}
echo "</ul>";
}
?>
You can fetch the parent categories and then construct a list for each subcategory like so:
<?php
$taxonomies = get_terms(array(
'taxonomy' => 'job_listing_category',
'hide_empty' => false,
'parent' => 0,
));
if (!empty($taxonomies)):
foreach ($taxonomies as $parent) {
$output = '<ul>';
$children = get_terms(array(
'taxonomy' => 'job_listing_category',
'parent' => $parent->term_id,
'hide_empty' => false,
));
foreach ($children as $child) {
$output .= '<li>' . esc_html($child->name) . '</li>';
}
$output = '</ul>';
}
echo $output;
endif;
Note that the code wasnt tested. Find more info here: https://developer.wordpress.org/reference/functions/get_terms/
I'm in the process of creating a custom category walker for my WordPress site. This will be part of my main menu and will show all top level categories with the children of the categories shown in a dropdown menu.
What I'd like to do is create a mega menu effect and as a result I'd like to repeat the parent category name in my dropdown inside a span so I can use it as a heading.
The code for my walker so far is as follows:
class Nav_Catwalker extends Walker_Category {
// Configure the start of each level
function start_lvl(&$output, $depth = 0, $args = array()) {
$indent = str_repeat("\t", $depth);
$output .= "<div class='sub-categories'>\n<span>" . $parent_category . "</span>\n$indent<ul class='sub-nav'>\n";
}
// Configure the end of each level
function end_lvl(&$output, $depth = 0, $args = array()) {
$indent = str_repeat("\t", $depth);
$output .= "$indent</ul>\n</div>\n";
}
// Configure the start of each element
function start_el( &$output, $category, $depth = 0, $args = array(), $id = 0) {
// Set the category name as a variable for later use
$cat_name = esc_attr( $category->name );
$cat_name = apply_filters( 'list_cats', $cat_name, $category );
// Configure the output for the top list element and its URL
if ( $depth === 0 ) {
$link = '' . $cat_name . '';
$output .= "\t<li class='parent-category'>$link\n";
}
// Configure the output for lower level list elements and their URL's
if ( $depth > 0 ) {
$link = '<a href="' . esc_url( get_term_link($category) ) . '"' . '>' . $cat_name . '</a>';
$output .= "\t<li class='sub-category'>$link\n";
}
}
// Configure the end of each element
function end_el(&$output, $page, $depth = 0, $args = array() ) {
$output .= "</li>";
}
}
What I need to do is create a variable that will replace the $parent_category variable in the first output (start_lvl) that will show the parent category of the sub-menu. I can't figure out how to do this.
Any help would be appreciated.
Thanks,
James
For future reference, I achieved this by restructuring my walker so I could use the existing $cat_name variable. The code is below.
class Navigation_Catwalker extends Walker_Category {
// Configure the start of each level
function start_lvl(&$output, $depth = 0, $args = array()) {
$output .= "";
}
// Configure the end of each level
function end_lvl(&$output, $depth = 0, $args = array()) {
$output .= "";
}
// Configure the start of each element
function start_el( &$output, $category, $depth = 0, $args = array(), $id = 0) {
// Set the category name and slug as a variables for later use
$cat_name = esc_attr( $category->name );
$cat_name = apply_filters( 'list_cats', $cat_name, $category );
$cat_slug = esc_attr( $category->slug );
// Configure the output for the top list element and its URL
if ( $depth === 0 ) {
$link = '<a class="parent-category-dropdown" href="' . esc_url( get_term_link($category) ) . '"' . '>' . $cat_name . '</a>';
$indent = str_repeat("\t", $depth);
$output .= "\t<li class='parent-category " . $cat_slug . "'>$link\n<div class='category-dropdown'>\n<span class='parent-category-title'>" . $cat_name . "</span>\n$indent<ul class='submenu'>\n";
}
// Configure the output for lower level list elements and their URL's
if ( $depth > 0 ) {
$link = '<a href="' . esc_url( get_term_link($category) ) . '"' . '>' . $cat_name . '</a>';
$output .= "\t<li class='sub-category'>$link\n";
}
}
// Configure the end of each element
function end_el(&$output, $page, $depth = 0, $args = array() ) {
if ( $depth === 0 ) {
$indent = str_repeat("\t", $depth);
$output .= "$indent</ul>\n</div>\n";
}
if ( $depth > 0 ) {
$output .= "</li>";
}
}
}
I've been trying to display the subtitle for each children page of the current parent page. At the moment i've got it working so that it shows all the title's of the children pages.
Basically I want it to show the subtitle underneath each title of the children pages.
// Get childern
$children = ($post->post_parent) ? wp_list_pages('title_li=&child_of='.$post->post_parent.'&echo=0') : wp_list_pages('title_li=&child_of='.$post->ID.'&echo=0');
// Set subtitle
$subtitle = get_the_title($post->the_subtitle);
echo $children;
echo $subtitle;
Any help will be much appreciated.
Cheers
You have two options for this:
1. The OOP approach
Extend the Walker_page class to create a custom iterator to use with wp_list_pages().
Add this to your functions.php:
class Subtitle_walker extends Walker_page {
function start_el(&$output, $page, $depth, $args, $current_page) {
if ( $depth )
$indent = str_repeat("\t", $depth);
else
$indent = '';
extract($args, EXTR_SKIP);
$css_class = array('page_item', 'page-item-'.$page->ID);
if ( !empty($current_page) ) {
$_current_page = get_page( $current_page );
_get_post_ancestors($_current_page);
if ( isset($_current_page->ancestors) && in_array($page->ID, (array) $_current_page->ancestors) )
$css_class[] = 'current_page_ancestor';
if ( $page->ID == $current_page )
$css_class[] = 'current_page_item';
elseif ( $_current_page && $page->ID == $_current_page->post_parent )
$css_class[] = 'current_page_parent';
} elseif ( $page->ID == get_option('page_for_posts') ) {
$css_class[] = 'current_page_parent';
}
$css_class = implode( ' ', apply_filters( 'page_css_class', $css_class, $page, $depth, $args, $current_page ) );
//Added subtitle support
$output .= $indent . '<li class="' . $css_class . '">' . $link_before . apply_filters( 'the_title', $page->post_title, $page->ID ) . $link_after . get_the_post_thumbnail($page->ID, array(72,72)) .''.' <span class="subtitle">'.get_the_subtitle($page->ID,'','',0).'</span>';
if ( !empty($show_date) ) {
if ( 'modified' == $show_date )
$time = $page->post_modified;
else
$time = $page->post_date;
$output .= " " . mysql2date($date_format, $time);
}
}
}
And call it in your template file:
$subtitle_menu = new Subtitle_walker();
$args = array(
'title_li' => '',
'child_of' => ($post->post_parent) ? $post->post_parent : $post->ID,
'echo' => 0,
'walker' => $subtitle_menu
);
$children = wp_list_pages($args);
echo $children;
Note: the previous code is based on this tutorial, you can read it to get an in-depth explanation of what it's doing
2. Using custom WP_Query loop
You can use get_page_children to query the child pages and then loop through them and build/echo your custom list items:
//Set up the objects needed
$my_wp_query = new WP_Query();
$all_wp_pages = $my_wp_query->query(array('post_type' => 'page'));
//Get children
$children = ($post->post_parent) ? get_page_children( $post->post_parent, $all_wp_pages ) : get_page_children( $post->ID, $all_wp_pages );
//Build custom items
foreach($children as $child){
echo '<li class="page-item">';
echo ''.get_the_title($child->ID).'<br/>';
echo '<span class="subtitle">'.get_the_subtitle($child->ID).'</span>';
echo '</li>';
}