I need to customise the output of wp_list_categories to show the top 6 categories, in the following format:
<ul>
<li>
<img src="img/CATEGORY_SLUG.jpg" alt="CATEGORY_NAME icon" />
<a href="CATEGORY_LINK">CATEGORY_NAME</a>
</li>
<li class="last">
<img src="img/CATEGORY_SLUG.jpg" alt="CATEGORY_NAME icon" />
<a href="CATEGORY_LINK">CATEGORY_NAME</a>
</li>
<li>
<img src="img/CATEGORY_SLUG.jpg" alt="CATEGORY_NAME icon" />
<a href="CATEGORY_LINK">CATEGORY_NAME</a>
</li>
<li class="last">
<img src="img/CATEGORY_SLUG.jpg" alt="CATEGORY_NAME icon" />
<a href="CATEGORY_LINK">CATEGORY_NAME</a>
</li>
<li>
<img src="img/CATEGORY_SLUG.jpg" alt="CATEGORY_NAME icon" />
<a href="CATEGORY_LINK">CATEGORY_NAME</a>
</li>
<li class="last">
<img src="img/CATEGORY_SLUG.jpg" alt="CATEGORY_NAME icon" />
<a href="CATEGORY_LINK">CATEGORY_NAME</a>
</li>
</ul>
I'm currently using the following, which obviously doesn't output the images or add 'last' to alternate LI tags:
<ul>
<?php wp_list_categories( array( 'orderby' => 'count', 'order' => 'DESC', 'show_count' => 'TRUE', 'title_li' => '', 'number' => '6' ) ); ?>
</ul>
So I need:
* Order by most popular cats, limit to six entries (as set already)
* Output CATEGORY_SLUG inside the IMG tag
* Output cat name
* Alternate between no class (or 'first' or something like that, if it's easier) and 'last'
Thanks!
Ivaylo Draganov answers:
Hi, you should use <em>get_categories</em> function (<em>wp_list_categories</em> uses it anyway), because then you get full control over the output. Try something like this:
$args=array(
'orderby' => 'count',
'order' => 'DESC',
'show_count' => true,
'title_li' => '',
'number' => 6
);
$categories = get_categories($args);
foreach($categories as $category) {
$output = '<li>';
$output .= '<img src="img/' . $category->slug . '.jpg" alt="' . $category->name . ' icon" />';
$output .= '<a href="' . get_category_link($category->term_id) . '">' . $category->name . '</a>';
$output =. '</li>';
}
If you plan on using it in multiple places you can wrap it in as a function.
For the alternating classes I'd have to dig a little bit (it's a simple PHP counter but it turns out that I can't do it straight). Or you could just do it with CSS (if you don't have to account for some of our old browser friends)
Ivaylo Draganov comments:
Updated code, wrapped as a function:
function my_list_categories( $args ) {
// get category objects
$categories = get_categories($args);
// class alternator
$odd_or_even = 'odd';
// loop objects
foreach($categories as $category) {
// build output
$output = '<li class="' . $odd_or_even . '">';
$output .= '<img src="img/' . $category->slug . '.jpg" alt="' . $category->name . ' icon" />';
$output .= '<a href="' . get_category_link($category->term_id) . '">' . $category->name . '</a>';
$output =. '</li>';
$odd_or_even = ('odd'==$odd_or_even) ? 'even' : 'odd';
}
// return output
return $output;
}
Put the above code in <em>functions.php</em> and then call it in your template with the same arguments that you use for <em>wp_list_categories()</em>(omitting <em>title_li</em> and <em>show_count</em>):
<?php my_list_categories( array( 'orderby' => 'count', 'order' => 'DESC', 'number' => '6' ) ); ?>
Jon comments:
Thanks Ivaylo - that looks promising, but I can't seem to get it to work - I dropped the code into functions.php and then tried calling it (it's in my footer) but I get a 500 error as soon as I try loading the page. Any ideas?
Ivaylo Draganov comments:
I'm sorry, there were two syntax errors. That was because I wrote the code without testing it. Here's the fixed (tested & working) version:
function my_list_categories( $args ) {
// get category objects
$categories = get_categories($args);
// class alternator
$odd_or_even = 'odd';
// loop objects
foreach($categories as $category) {
// build output
$output = '<li class="' . $odd_or_even . '">';
$output .= '<img src="img/' . $category->slug . '.jpg" alt="' . $category->name . ' icon" />';
$output .= '<a href="' . get_category_link($category->term_id) . '">' . $category->name . '(' . $category->category_count . ')</a>';
$output .= '</li>';
$odd_or_even = ('odd'==$odd_or_even) ? 'even' : 'odd';
}
// return output
return $output;
}
I also forgot to mention that you'd have to echo the result of the function:
<?php echo my_list_categories( array( 'orderby' => 'count', 'order' => 'DESC', 'number' => 6 ) ); ?>
Jon comments:
Thanks for the quick reply - looks like it's almost there, but seems to be outputting only the sixth most popular cat, not the whole top 6?
Ivaylo Draganov comments:
This time it should work as expected:
function my_list_categories( $args ) {
// get category objects
$categories = get_categories($args);
// set vars
$odd_or_even = 'odd';
$output = '';
// loop objects
foreach($categories as $category) {
// build output
$output .= '<li class="' . $odd_or_even . '">';
$output .= '<img src="img/' . $category->slug . '.jpg" alt="' . $category->name . ' icon" />';
$output .= '<a href="' . get_category_link($category->term_id) . '">' . $category->name . '(' . $category->category_count . ')</a>';
$output .= '</li>';
$odd_or_even = ('odd'==$odd_or_even) ? 'even' : 'odd';
}
// return output
return $output;
}
Jon comments:
Brilliant - thanks a lot!
Dan | gteh answers:
If you want to add a class to every other <li>, use CSS3
li:nth-child(odd) { background-color:#eee; }
li:nth-child(even) { background-color:#fff; }
assign your .last styles to either odd or even