I know there are lots of questions and answers out there for this very thing, but I'm having a hard time putting it all together. The goal is to get a <ul>
with category names as the <li>
, then each <li>
will have a nested <ul>
to list the posts in that category. Something like
Hotels
- Best Western
- Holiday Inn
Restaurants
- Burger King
- McDonald's
I came up with this code:
<?php
$categories = get_categories(
array (
'post_type' => 'attractions', // does nothing
'orderby' => 'name',
'order' => 'asc'
)
);
foreach ($categories as $category){
echo '<li class="category-list-item">';
echo '<h2 class="bluegreen allcaps">' . $category->name . '</h2>';
echo '<ul class="attractions-list">';
$catPosts = new WP_Query(
array (
'post_type' => 'attractions', //breaks page
'category_name' => $category->slug,
'orderby' => 'title'
)
);
if ( $catPosts->have_posts() ){
while ( $catPost->have_posts() ){
$catPost->the_post(); ?>
<li class="attractions-list-item">
<a target="_blank" href="<?php echo get_field('website_url', $post->ID); ?>"><?php the_title(); ?></a>
</li>
<?php
} //end while
}//end if
echo '</ul>';
echo '</li>';
} //end foreach
wp_reset_postdata();
?>
In the get_categories()
array, adding the post_type
doesn't do anything. Further down, I added it to the WP_Query
array and that breaks the page (basically it will display the first category name alphabetically, then the rest of the page—such as the footer and stuff—doesn't show up). I've tried declaring the post_type
in each place individually and both places at the same time but the results don't change.
With that, I was able to get everything to display, but the order was all janky and I couldn't figure out how to sort it. Here's what I ended up with from going down that road:
<ul class="category-list">
<?php
$args = array(
'post_type' => 'attractions',
'posts_per_page' => -1,
'orderby' => 'name', //also tried 'slug', which changes the order but still doesn't make sense
'exclude' => '1'
);
$query = new WP_Query($args);
$q = array();
while ( $query->have_posts() ) {
$query->the_post();
$a = '<li class="attractions-list-item">' . get_the_title() .'</li>';
$categories = get_the_category();
foreach ( $categories as $key=>$category ) {
$b = '<li class="categories-list-item"><a class="anchor" name="' . $category->slug . '"></a><h2 class="bluegreen allcaps">' . $category->name . '</h2>';
}
$q[$b][] = $a; // Create an array with the category names and post titles
}
/* Restore original Post Data */
wp_reset_postdata();
foreach ($q as $key=>$values) {
echo $key;
echo '<ul class="attractions-list">';
foreach ($values as $value){
echo $value;
}
echo '</ul>';
}
echo '</li>';
?>
</ul>
In the end, with method one, I'm able to return a complete, alphabetically ordered list of categories but no posts (assuming because I'm having a hard time declaring a post_type
other than the default posts). With method two, I can get all the categories and the posts beneath them, but they're in a weird, nonsensical order and I can't figure out how to sort them. The posts under each category are also in a weird order.
I know this is a crazy long post, but I'm at my wit's end at this point!! Thanks in advance for any help, suggestions or insights!!
I know there are lots of questions and answers out there for this very thing, but I'm having a hard time putting it all together. The goal is to get a <ul>
with category names as the <li>
, then each <li>
will have a nested <ul>
to list the posts in that category. Something like
Hotels
- Best Western
- Holiday Inn
Restaurants
- Burger King
- McDonald's
I came up with this code:
<?php
$categories = get_categories(
array (
'post_type' => 'attractions', // does nothing
'orderby' => 'name',
'order' => 'asc'
)
);
foreach ($categories as $category){
echo '<li class="category-list-item">';
echo '<h2 class="bluegreen allcaps">' . $category->name . '</h2>';
echo '<ul class="attractions-list">';
$catPosts = new WP_Query(
array (
'post_type' => 'attractions', //breaks page
'category_name' => $category->slug,
'orderby' => 'title'
)
);
if ( $catPosts->have_posts() ){
while ( $catPost->have_posts() ){
$catPost->the_post(); ?>
<li class="attractions-list-item">
<a target="_blank" href="<?php echo get_field('website_url', $post->ID); ?>"><?php the_title(); ?></a>
</li>
<?php
} //end while
}//end if
echo '</ul>';
echo '</li>';
} //end foreach
wp_reset_postdata();
?>
In the get_categories()
array, adding the post_type
doesn't do anything. Further down, I added it to the WP_Query
array and that breaks the page (basically it will display the first category name alphabetically, then the rest of the page—such as the footer and stuff—doesn't show up). I've tried declaring the post_type
in each place individually and both places at the same time but the results don't change.
With that, I was able to get everything to display, but the order was all janky and I couldn't figure out how to sort it. Here's what I ended up with from going down that road:
<ul class="category-list">
<?php
$args = array(
'post_type' => 'attractions',
'posts_per_page' => -1,
'orderby' => 'name', //also tried 'slug', which changes the order but still doesn't make sense
'exclude' => '1'
);
$query = new WP_Query($args);
$q = array();
while ( $query->have_posts() ) {
$query->the_post();
$a = '<li class="attractions-list-item">' . get_the_title() .'</li>';
$categories = get_the_category();
foreach ( $categories as $key=>$category ) {
$b = '<li class="categories-list-item"><a class="anchor" name="' . $category->slug . '"></a><h2 class="bluegreen allcaps">' . $category->name . '</h2>';
}
$q[$b][] = $a; // Create an array with the category names and post titles
}
/* Restore original Post Data */
wp_reset_postdata();
foreach ($q as $key=>$values) {
echo $key;
echo '<ul class="attractions-list">';
foreach ($values as $value){
echo $value;
}
echo '</ul>';
}
echo '</li>';
?>
</ul>
In the end, with method one, I'm able to return a complete, alphabetically ordered list of categories but no posts (assuming because I'm having a hard time declaring a post_type
other than the default posts). With method two, I can get all the categories and the posts beneath them, but they're in a weird, nonsensical order and I can't figure out how to sort them. The posts under each category are also in a weird order.
I know this is a crazy long post, but I'm at my wit's end at this point!! Thanks in advance for any help, suggestions or insights!!
This is a lot simpler than you might believe, first, I must dispel some misconceptions:
post_type
is not a parameter of get_categories
, isn't listed in the documentation, and wouldn't make sense. Categories are terms not posts, they don't have a post type, and this API call retrieves terms, it has no business looking into the posts tableget_categories
are higher level helper functions, mostly there for backwards compatibility. As a result they tend to have "strings attached". Use the terms API instead, it works the same for all taxonomies be they tags, categories, or something you registered yourself.WP_Error
object?get_template_part
is an amazing function, don't ignore it and write super long files, break it upesc_html
etcSo finally, you kind of had the answer to begin with:
grab the terms
for each term
display the terms title
grab the posts of type "attractions" that have that term
for each post
display it
So lets break that apart and fetch the terms:
$terms = get_terms([
'taxonomy' => 'category',
'order' => 'asc',
'orderby' => 'name',
]);
if ( !empty( $terms ) && !is_wp_error( $terms ) ) {
echo '<h3>'.esc_html( $term->name ).'</h3>';
foreach ( $terms as $term ) {
// .. display posts
}
}
Then for your post loop:
$args = [
'post_type' => 'attractions',
'cat' => $term->term_id,
];
$query = new WP_Query( $args );
// etc..
post_type
option toget_categories
, is there a specific reason you chose to reuse the categories taxonomy that came with WP by default rather than creating a new custom taxonomy, e.g.attraction_type
? Or why you're using the category specific APIs rather than the general taxonomy APIs? – Tom J Nowell ♦ Commented Dec 29, 2018 at 0:21