Ask your WordPress questions! Pay money and get answers fast! (more info)

category.php customization WordPress

  • SOLVED

I need to build a categories.php template that will look like the attached file.

1. I have 3 category levels:
> parent > children > grandchildren

2. When the parent category is requested:
- category.php should return the child categories
- each child category should have an adjacent but separate list of grandchildren

3. When a child category is requested:
- category.php should return the grandchild categories

I don't need you to code the entire category.php file.

I just need you to help me set up the control structure (aka The Loop), especially for how to handle requests for the parent and child categories.

I am willing to negotiate on the cost of this work.

I can supply more mockups and wireframes, if needed.

Answers (6)

2014-07-08

John Cotton answers:


<?php

function category_has_parent( $cat_id ){
$category = get_category( $cat_id );
return ($category->category_parent > 0);
}


global $cat;

$children = get_terms( 'category', array( 'parent' => $cat ) ); // Set other args if necessary

if( category_has_parent($cat) ) {
if( count($children) == 0 ) {
// You're at the grandchild level (OR YOU MIGHT HAVE A PARENT WITH NO GRANDCHILD - BEWARE!)

} else {
// You're at the child level

}
} else {
// You're at the parent level
foreach( $children as $child ) {
// Do your child layout
$grand_children = get_terms( 'category', array( 'parent' => $child->term_id ) );

}
}


dirtcastle comments:

Thank you for your response! I am able to get the parent level working with the following:


$option = '<article class="post type-post status-publish format-standard hentry category-genres">';
$option .= '<a href="'.get_category_link( $category_id ).$child->slug.'">'.$child->name.'</a>';
$option .= $child->description;
$option .= '</article>';
echo $option;


But I still need to figure out two things:

1. <strong>I can't get the other levels (children and grandchildren) of your control structure to work.</strong> Could you take the approach I have used for the parent level and help me apply that to the other levels?

2. On the parent level, <strong>I need each category box to display all the categories that are one level below it.</strong> See the attached image. At the parent level, each child category should contain all of its grandchildren. In other words, when viewing the parent level, the user should see three levels of categories, nested as it is in the image. Showing three levels is only possible on the parent level. For the child level I will be putting posts where the grandchildren are, but for now let's just have 2-levels of categories at the child level.

Thank you for helping me with this!


John Cotton comments:

I think you need to should me more of your code - I'm not clear where the code you've posted sits.


dirtcastle comments:

Thanks!


<?php
function category_has_parent( $cat_id ){
$category = get_category( $cat_id );
return ($category->category_parent > 0);
}
global $cat;
$children = get_terms( 'category', array( 'parent' => $cat ) ); // Set other args if necessary
if( category_has_parent($cat) ) {
if( count($children) == 0 ) {

// You're at the grandchild level (OR YOU MIGHT HAVE A PARENT WITH NO GRANDCHILD - BEWARE!)

} else {

// You're at the child level

}
} else {

// You're at the parent level
foreach( $children as $child ) {
// Do your child layout
$grand_children = get_terms( 'category', array( 'parent' => $child->term_id ) );
$option = '<article class="post type-post status-publish format-standard hentry category-genres">';
$option .= '<a href="'.get_category_link( $category_id ).$child->slug.'">'.$child->name.'</a>';
$option .= $child->description;
$option .= '</article>';
echo $option;

}
}
?>


John Cotton comments:

Surely this line
$option .= '<a href="'.get_category_link( $category_id ).$child->slug.'">'.$child->name.'</a>';
should be
$option .= '<a href="'.get_category_link( $child->term_id ).'">'.$child->name.'</a>';
?

And clicking on that link should display the output from "// You're at the child level" (so you might want to put some echo in there to demonstrate that.


dirtcastle comments:

Yes! It is now working on the different levels. Woot!

Can you help me with how to display the grandchildren (nested within each child category box) on the parent level? After that, I think I'll be ready for the upvote. :-)


function category_has_parent( $cat_id ){
$category = get_category( $cat_id );
return ($category->category_parent > 0);
}
global $cat;
$children = get_terms( 'category', array( 'parent' => $cat ) ); // Set other args if necessary
if( category_has_parent($cat) ) {
if( count($children) == 0 ) {

// You're at the grandchild level (OR YOU MIGHT HAVE A PARENT WITH NO GRANDCHILD - BEWARE!)

} else {

// You're at the parent level
foreach( $children as $child ) {
// Do your child layout
$grand_children = get_terms( 'category', array( 'parent' => $child->term_id ) );
$option = '<article class="post type-post status-publish format-standard hentry category-genres">';
$option .= '<a href="'.get_category_link( $child->term_id ).'">'.$child->name.'</a>';
$option .= $child->description;
$option .= '</article>';
echo $option;

}

}
} else {

// You're at the parent level
foreach( $children as $child ) {
// Do your child layout
$grand_children = get_terms( 'category', array( 'parent' => $child->term_id ) );
$option = '<article class="post type-post status-publish format-standard hentry category-genres">';
$option .= '<a href="'.get_category_link( $child->term_id ).'">'.$child->name.'</a>';
$option .= $child->description;
$option .= '</article>';
echo $option;

}
}
?>


John Cotton comments:


// You're at the parent level

foreach( $children as $child ) {
// Do your child layout
$option = '<article class="post type-post status-publish format-standard hentry category-genres">';

$option .= '<a href="'.get_category_link( $child->term_id ).'">'.$child->name.'</a>';

$option .= $child->description;

$grandchildren = get_terms( 'category', array( 'parent' => $child->term_id ) );

foreach( $grandchildren as $grandchild ) {
$option .= sprintf( '<span class="grandchild">%s</span>', $grandchild->name );
}

$option .= '</article>';

echo $option;

}


dirtcastle comments:

Yes! Yes! Yes!

I'm glad I asked for help here on wpquestions.com, because I would not have been able to figure this out on my own.

Your code is very elegant, efficient, and easy to understand.

Upvotes are on their way!

2014-07-08

Sébastien | French WordpressDesigner answers:

no problem :)


Sébastien | French WordpressDesigner comments:

the attachment is the template of a parent category. That's it ?
Have you an image for the template of a chidren category ?


Sébastien | French WordpressDesigner comments:

if you want, use my email : [email protected]


Sébastien | French WordpressDesigner comments:

This is the template for parnt catgeory and children category and grandchildren category.
Its name is category.php
Save your current category.php and paste this one in your theme.
That's it :)


<?php get_header();

function category_has_parent( $cat_id ){
$category = get_category( $cat_id );
return ($category->category_parent > 0);
}


global $cat;
$children = get_terms( 'category', array( 'parent' => $cat, 'hide_empty' => false ) );


if( category_has_parent($cat) ) {


if( count($children) == 0 ) {
/**************************************** this loop is for the GRANDCHILD LEVEL */
echo "GRANDCHILD LEVEL";
echo '<h2>Category : ';
single_cat_title();
echo '</h2>';



} else {


/**************************************** this loop is for the CHILD LEVEL */
echo "CHILD LEVEL";
echo '<h2>Category : ';
single_cat_title();
echo '</h2>';

echo 'child of this category : ';
foreach ($children as $c) {
$category_link = get_category_link( $c->term_id );
echo '<a href="' . $category_link . '">' . $c->name . '</a> ';
}


}


} else {


/**************************************** this loop is for the PARENT LEVEL */
echo "PARENT LEVEL";
echo '<h2>Category : ';
single_cat_title();
echo '</h2>';
if($children) {
foreach( $children as $child ) {
$grand_children = get_terms( 'category', array( 'parent' => $child->term_id,'hide_empty' => false ) );
if($grand_children) {
echo "list of grandchildrens categories : "
foreach ($grand_children as $g_children) {
$category_link = get_category_link( $g_children->term_id );
echo '<a href="' . $category_link . '">' . $g_children->name . '</a> ';
}
}
}
}


}


get_footer(); ?>

2014-07-08

Ellah Alzona answers:

Get parent first:


<?php
$parentId = 25;
include('loop.php');

?>


Inside loop.php


<?php

global $post;
$args = array(
'type' => 'post',
'child_of' => 0,
'parent' => $parentId,
'orderby' => 'name',
'order' => 'ASC',
'hide_empty' => 1,
'hierarchical' => 1,
'exclude' => '',
'include' => '',
'number' => '',
'taxonomy' => 'category',
'pad_counts' => false
);

$categories = get_categories( $args );

?>

<!-- / Then get the Sub cats -->


<?php
// initialize the ctr
$ctr=1;

// get the last number
$lastItem = count($categories);

// loopiing..
foreach ($categories as $key => $value) {

if ($ctr==1)
{
echo '<li class="active">
<a href="#'.$value->slug.'" rel="bookmark"data-toggle="tab">'.$value->name.'</a>
</li> <span style="font-size: 30px;"> &bull; </span>';
}
else
{
echo '<li><a href="#'.$value->slug.'" rel="bookmark"data-toggle="tab">'.$value->name.'</a></li>';
if ($lastItem!=$ctr)
{
echo '<span style="font-size: 30px;"> &bull; </span>';
}
}

$ctr++;

}

?>


<div class="tab-content">

<?php

$contentCtr=1;
$classActive= "active";

foreach ($categories as $key => $value)
{
if($contentCtr!=1)
{
$classActive= "";
}

?>
<div class="tab-pane <?= $classActive?>" id="<?=$value->slug?>">
<div class="display-category-images">
<ul>
<?php
$args = array( 'category_name' => $value->slug, 'posts_per_page' => '20' );

$posts = get_posts( $args );

foreach( $posts as $post ): setup_postdata($post);

$image = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), 'single-post-thumbnail' );
$url = $image[0];

$idAction = str_replace('-', '', $value->slug)
?>

<li>
<a rel="candy" data-toggle="modal" data-target="#<?=$idAction.$post->ID?>" class="product">
<img src="<?= $url?>" class="img-responsive prodimg">

<?=the_title();?>
</a>
</li>


<?php endforeach; ?>

</ul>
</div>
</div>

<?php

$contentCtr++;
}

?>

</div>




I hope it helps a litte.

2014-07-08

Daniel Yoen answers:

Hello,

Your code is something like this :

<?php

//get current category
$current_tax_id = intval(get_queried_object_id());

//get current category children
$get_term_childrens = get_term_children($current_tax_id, 'your_taxonomy'); //change me

//check if current category has children
if($get_term_childrens)
{
//loop
foreach($get_term_childrens as $term_children)
{
//you can use this variable to get category cetails
$term_children_id = intval($term_children->term_id);

/** -- children loop -- **/

//get children category children
$get_term_grand_childrens = get_term_children($term_children_id, 'your_taxonomy'); //change me

//check if child category has children
if($get_term_grand_childrens)
{
//grand children loop
foreach($get_term_grand_childrens as $term_grand_children)
{
//you can use this variable to get category cetails
$term_grand_children_id = intval($term_grand_children->term_id);

/** -- grand children loop -- **/
}
}
}
}

?>


hope this help :-)

2014-07-08

timDesain Nanang answers:

<strong>raw mode</strong>


global $cat;

$cat_id = $cat;
$taxonomy = 'category';

$get_child = get_terms( $taxonomy, array( 'parent' => $cat_id ) );
$child_size = sizeof($get_child);
$cat_now = get_term_by( 'id', $cat_id, $taxonomy);
$get_parent = get_term( $cat_now->parent, $taxonomy );
$parent_id = !is_wp_error( $get_parent ) ? $get_parent->term_id : 0;

//child
if($child_size>0 AND $parent_id>0){
echo '<h3>child</h3>';
echo '<br /><pre>'; print_r($get_child).'</pre>';
}
//parent
elseif($child_size>0){
echo '<h3>parent</h3>';
echo '<br /><pre>'; print_r($get_child).'</pre>';
//get
foreach($get_child as $c){
$get_grand = get_terms( $taxonomy, array( 'parent' => $c->term_id ) );
echo '<br /><pre>'; print_r($get_grand).'</pre>';
}

}
//grandchild
else{
echo '<h3>grandchild</h3>';
}


timDesain Nanang comments:

<strong>another mode </strong>
output: see attachment

i am using twentyten theme


global $cat;
$cat_id = $cat;
$taxonomy = 'category';

$get_child = get_terms( $taxonomy, array( 'parent' => $cat_id, 'hide_empty' => false ) );
$child_size = sizeof($get_child);
$cat_now = get_term_by( 'id', $cat_id, $taxonomy);
$get_parent = get_term( $cat_now->parent, $taxonomy );
$parent_id = !is_wp_error( $get_parent ) ? $get_parent->term_id : 0;

//CHILD
if($child_size>0 AND $parent_id>0){
echo '<h3>CHILD</h3>';
echo '<ul>';
foreach($get_child as $c){
echo '<li><a href="'.esc_attr(get_term_link( $c, $taxonomy )).'">'.$c->name.'</a>';
echo '<p>'.$c->description.'</p>';
echo '</li>';
}
echo '</ul>';
}

//PARENT
elseif($child_size>0){
echo '<h3>PARENT</h3>';
echo '<ul>';
foreach($get_child as $c){
echo '<li><a href="'.esc_attr(get_term_link( $c, $taxonomy )).'">'.$c->name.'</a>';
echo '<p>'.$c->description.'</p>';
$get_grand = get_terms( $taxonomy, array( 'parent' => $c->term_id, 'hide_empty' => false ) );
echo '<ul>';
foreach($get_grand as $g){
echo '<li><a href="'.esc_attr(get_term_link( $g, $taxonomy )).'">'.$g->name.'</a></li>';
}
echo '</ul>';
echo '</li>';
}
echo '</ul>';
}

//GRANDCHILD
else{
echo '<h3>GRANDCHILD</h3>';
//you can put post loop here
}