-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Description
@ntsekouras has asked that I come up with a list of scenarios that the Breadcrumbs block should handle based on my experience. Currently, the block only automatically handles singular post type views for hierarchical post types and post types + assigned taxonomy term at a basic level.
Below, I will list out an extensive variety of scenarios that the block may handle. These are broken down into types and subtypes of webpages based on the queried data. It's not a 100% exhaustive list, but it covers most scenarios that you'll see (hope I didn't leave anything out).
Singular Views - is_singular()
This is the hardest thing to get right, and in my study of breadcrumbs over the years, it's rare that any plugin covers every possible use case. Sometimes it's best guesses and sometimes just having good defaults. That's why it's generally important to make this as extensible as possible.
Posts - is_singular('post')
There are two common scenarios for blog posts that users prefer. One is to display a taxonomy term as part of the breadcrumb trail. The other is to use the permalink structure. And sometimes even a combination of the two. Here are several of many possibilities:
// With categories
Home > Category A > Category B > Post Title
// With tags
Home > Tag X > Post Title
// With rewrite front of 'articles'
Home > Articles > Post Type
// With date-based permalinks:
Home > Year > Month > Day > Post Title
// With rewrite front of 'articles' and date-based permalinks
Home > Articles > Year > Month > Day > Post Title
Pages - is_page()
This is generally pretty straightforward:
Home > Page Title
Home > Parent > Page Title
Attachments - is_attachment()
Attachments are a post type that can both have a parent post or not have one at all. However, it is not a hierarchical post type. Here are some scenarios:
// No parent post
Home > Attachment Title
// With parent page
Home > Parent > Page Title > Attachment Title
// With parent post (that has taxonomy term in trail)
Home > Category > Post Title > Attachment Title
// With parent post (that has date-based trail)
Home > Year > Month > Day > Post Title > Attachment Title
Singular Custom Post Types - is_singular($post_type)
These should be handled much the same as posts, pages, and attachments. But this is where it gets extremely hard to handle everything perfectly and where extensibility is important for plugin authors.
Hierarchy - is_post_type_hierarchical() || $post->post_parent > 0
As shown with pages and attachments, posts of a given type can have a parent post.
// Hierarchical (like pages)
Home > Post Type Archive > Parent > Post Title
// With parent post of different type (studio and film types)
Home > Studio Archive > Studio Title > Film Title
// If the post type supports rewrite front.
// With a rewrite front of 'archives'
Home > Archives > Post Type Archive > Parent > Post Title
Home > Archives > Studio Archive > Studio Title > Film Title
No Hierarchy
These can get pretty complex too, but the two most common scenarios are:
// No taxonomy terms
Home > Post Type Archive > Post Title
// With taxonomy terms
Home > Post Type Archive > Category > Post Title
// If the post type supports rewrite front.
// With a rewrite front of 'archives'
Home > Archives > Post Type Archive > Post Title
Home > Archives > Post Type Archive > Category > Post Title
Custom post types can use rewrite tags as well, such as %author%, just like posts. I've already explained those in the Posts section above.
Archives - is_archive()
WordPress has a lot of different archive types, particularly when you get into date and time-based archives. Below is a fairly extensive, but not exhaustive, list of scenarios.
Post Type Archive - is_post_type_archive()
Occurs when viewing a post type archive. This is one of the more complex breadcrumb types if you truly want to support custom post types. Plugin authors can use any path for their archives, including have their archive as a sub-path of an existing page.
At the most basic level, this would look like:
Home > Post Type
Home > Post Type > Page 2
You can also combine post type archive queries with author or search, for example:
Home > Post Type > Author
Home > Post Type > Search results for %s
I don't know how complex we want to get with this for Core, but there are a lot of scenarios.
Taxonomy Term Archive - is_category() || is_tag() || is_tax()
Taxonomy term archives can be nearly as complex as post type archives. It really just depends on how far you want to go with support for custom taxonomies. Plugin authors can use any path for their archives, including have their archive as a sub-path of an existing page.
At the most basic, you would support something like:
// Hierarchical
Home > Category A > Category B
// Non-hierarchical
Home > Post Tag
// Hierarchical w/post type archive
Home > Post Type Archive > Category A > Category B
// Non-hierarchical w/post type archive
Home > Post Type Archive > Tag
Generally speaking, it's probably good practice to automatically support the post type archive when a taxonomy is attached to a specific post type.
Author Archive - is_author()
This should be fairly straightforward:
Home > Author
See note above about authors and post type archives. When is_post_type_archive() && is_author() are combined.
Time and Date archives - is_time() || is_date()
WordPress supports an extensive number of time/date archives. It'd be hard to cover every scenario, but here are several of them that my plugin supports:
// Minute + Hour - get_query_var('minute') && get_query_var('hour')
Home > 9:45 am
// Minute - get_query_var('minute')
Home > Minute
// Hour - get_query_var('hour')
Home > Hour
// Day - is_day()
Home > Year > Month > Day
// Week - get_query_var('week')
Home > Year > Week
// Month - is_month()
Home > Year > Month
// Year - is_year()
Home > Year
Fallback - is_archive()
We should probably support a generic fallback for any use cases that aren't covered since it's pretty tough to cover every possible scenario:
Home > Archives
Home > Archives > Page 2
Front Page - is_front_page()
Generally speaking, you shouldn't need a breadcrumb when viewing the front page itself, but I've always had a user or two who have wanted to display it for consistency in design. I generally just have an option for enabling it.
Home
But it should handle paged pages. This is generally is_home() && is_paged() (see Pagination section below):
Home > Page 2
Search Results - is_search()
Nothing much needed here for most use cases:
Home > Search results for %s
Home > Search results for %s > Page 2
404 - is_404()
This one is pretty basic. It should be:
Home > 404 Not Found
Pagination - Special Case
Pagination is unique among breadcrumbs because there are multiple ways that archives, search results, home, and singular views can be paginated.
Paged - is_paged()
This occurs with the normal pagination of is_archive(), is_home(), and is_search():
// Home
Home > Page 2
// Search
Home > Search results for %s > Page 2
// Various archives
Home > 2025 > 10 > 20 > Page 2
Home > Category > Page 2
Home > Author > Page 2
Paged Singular - is_singular() && 1 < get_query_var('page')
This occurs on singular views when the user inserts the <!-- nextpage --> tag (Page Break block):
// Hierarchical
Home > Ancestor > Parent > Post Title > Page 2
// With Categories
Home > Category > Post Title > Page 2
Paged Query Block - [No Core Function]
There are times when users add a Query block to a page, post, etc. that is paginated I didn't think Core was handling this in past versions, but it seems to be working in my test case on Core/Gutenberg trunk at the moment. So this may not need additional handling (though does need testing) and will work like the above:
// Hierarchical
Home > Ancestor > Parent > Post Title > Page 2
// With Categories
Home > Category > Post Title > Page 2
Paged Comments - is_singular() && 1 < get_query_var('cpage')
This occurs on singular views when comments are paginated:
// Hierarchical
Home > Ancestor > Parent > Post Title > Comments Page 2
// With Categories
Home > Category > Post Title > Comments Page 2
Rewrite Front
Posts, attachments, and custom post types with "rewrite front" support ($GLOBALS['wp_rewrite']->front) are special cases. If the user sets this via the Permalinks settings screen, it can be anything. For example, it can be set to archives or even set to blog/archives.
The only time this matter is when the rewrite front matches an actual path that exists, such as a page named Archives or Blog > Archives.
I've covered these scenarios in the earlier examples but wanted to make a special note of it. It's an oft-overlooked WordPress feature in breadcrumb plugins.
Also note that date/time archives support rewrite front.