Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom breadcrumbs with list of children (categories or pages)

I am currently building my very first WordPress template (using Bootstrap 4) and I need to integrate breadcrumbs to my page. I can see that the theme we're currently using offers breadcrumbs as well, but as these are default breadcrumbs, it's by far not enough.

Default Breadcrumb, what I mean, is something simple as:
Home / Category / Subcategory / Page

What I need to build is more like:
Home / Category / Subcategory / Page as well, but when you hover Category oder Subcategory you should see the children of the currently selected option.

e.g. hovering HOME will display the available categories:

Home / Category / Subcategory / Page
  |
Category A
Category B
Category C


Or, to see the other available subcategories, it will look like this:

Home / Category / Subcategory / Page
         |
       Subcategory A
       Subcategory B
       Subcategory C

I have already build this for a static page. Code looks like this:

<div class="d-none d-md-block">
     <div class="dropdown">
          <div class="dropdown-menu">
               <a class="dropdown-item" href="~/Category1">Category 1</a>
               <a class="dropdown-item" href="~/Category2">Category 2</a>
               <a class="dropdown-item" href="~/Category3">Category 3</a>
          </div>

          <a class="dropdown-toggle" data-toggle="dropdown">
             Home
          </a>
     </div>

     <div class="dropdown">
          <div class="dropdown-menu">
               <a class="dropdown-item" href="~/Catgeory4/SubCat1">SubCat 1</a>
               <a class="dropdown-item" href="~/Catgeory4/SubCat2">SubCat 2</a>
               <a class="dropdown-item" href="~/Catgeory4/SubCat3">SubCat 3</a>
               <a class="dropdown-item" href="~/Catgeory4/SubCat4">SubCat 4</a>
          </div>

          <a class="dropdown-toggle" data-toggle="dropdown">
             Category 4
          </a>
     </div>

     <a href="~/Catgeory4/SubCat2/Page" class="crumb active">Page</a>
</div>

The problem is, that it's my first ever WordPress template and that I only have a basic idea of the wordpress specific php at all :-[ So if you know a plugin that offers this kind of structure, I will be glad to use this. If I have to build it inside the template, fine with me as well.. I just don't know how to get startetd here, so that it results in a dynamic piece of code...

PS (if it does help at all): this is the current get_breadrumb function from the base theme:

if ( ! function_exists( 'bizbuzz_get_breadcrumb' ) ) {
/**
 *  Header image / Slider.
 *
 * @since 1.0.0
 */
function bizbuzz_get_breadcrumb() {

    $enable_breadcrumb = bizbuzz_get_option( 'enable_breadcrumb' );
    if ( $enable_breadcrumb ) {
        $args = array(
            'separator'    => '>',
            'show_current' => 1,
            'show_on_home' => 0,
        );
        if ( is_home() || is_front_page() ) {

            if ( $args['show_on_home'] ) {
                ?>
                <div id="bizbuzz-breadcrumb">
                    <div class="rt-wrapper">
                        <?php bizbuzz_default_breadcrumb( $args ); ?>
                    </div>
                </div>
                <?php
            }
        } else {
            ?>
            <div id="bizbuzz-breadcrumb">
                <div class="rt-wrapper">
                    <?php bizbuzz_default_breadcrumb( $args ); ?>
                </div>
            </div>
            <?php
        }
     }
   }
}
like image 573
JonSnow Avatar asked Aug 10 '20 11:08

JonSnow


People also ask

How do I add categories to breadcrumbs in WordPress?

To display the breadcrumbs on your site, navigate to Appearance > Widgets. Then, select Widgets again from the menu. Here, you can add the Breadcrumb NavXT widget to your sidebar: As you can see, Breadcrumb NavXT is a very straightforward tool.

What is theme breadcrumb?

What Are WordPress Breadcrumbs? Breadcrumbs, as they relate to WordPress (or any website), are navigational links that appear at the top of a post or page. They show users the higher-level categories that led them to the content they're currently viewing and also enable easy navigation back to previously-viewed pages.


Video Answer


2 Answers

Try this code it's working from my side.

function custom_breadcrumbs()
{
    // Set variables for later use
    $here_text        = __( 'You are currently here!' );
    $home_link        = home_url('/');
    $home_text        = __( 'Home' );
    $link_before      = '<span typeof="v:Breadcrumb">';
    $link_after       = '</span>';
    $link_attr        = ' rel="v:url" property="v:title"';
    $link             = $link_before . '<a' . $link_attr . ' href="%1$s">%2$s</a>' . $link_after;
    $delimiter        = ' &raquo; ';              // Delimiter between crumbs
    $before           = '<span class="current">'; // Tag before the current crumb
    $after            = '</span>';                // Tag after the current crumb
    $page_addon       = '';                       // Adds the page number if the query is paged
    $breadcrumb_trail = '';
    $category_links   = '';

    /** 
     * Set our own $wp_the_query variable. Do not use the global variable version due to 
     * reliability
     */
    $wp_the_query   = $GLOBALS['wp_the_query'];
    $queried_object = $wp_the_query->get_queried_object();

    // Handle single post requests which includes single pages, posts and attatchments
    if ( is_singular() ) 
    {
        /** 
         * Set our own $post variable. Do not use the global variable version due to 
         * reliability. We will set $post_object variable to $GLOBALS['wp_the_query']
         */
        $post_object = sanitize_post( $queried_object );

        // Set variables 
        $title          = apply_filters( 'the_title', $post_object->post_title );
        $parent         = $post_object->post_parent;
        $post_type      = $post_object->post_type;
        $post_id        = $post_object->ID;
        $post_link      = $before . $title . $after;
        $parent_string  = '';
        $post_type_link = '';

        if ( 'post' === $post_type ) 
        {
            // Get the post categories
            $categories = get_the_category( $post_id );
            if ( $categories ) {
                // Lets grab the first category
                $category  = $categories[0];

                $category_links = get_category_parents( $category, true, $delimiter );
                $category_links = str_replace( '<a',   $link_before . '<a' . $link_attr, $category_links );
                $category_links = str_replace( '</a>', '</a>' . $link_after,             $category_links );
            }
        }

        if ( !in_array( $post_type, ['post', 'page', 'attachment'] ) )
        {
            $post_type_object = get_post_type_object( $post_type );
            $archive_link     = esc_url( get_post_type_archive_link( $post_type ) );

            $post_type_link   = sprintf( $link, $archive_link, $post_type_object->labels->singular_name );
        }

        // Get post parents if $parent !== 0
        if ( 0 !== $parent ) 
        {
            $parent_links = [];
            while ( $parent ) {
                $post_parent = get_post( $parent );

                $parent_links[] = sprintf( $link, esc_url( get_permalink( $post_parent->ID ) ), get_the_title( $post_parent->ID ) );

                $parent = $post_parent->post_parent;
            }

            $parent_links = array_reverse( $parent_links );

            $parent_string = implode( $delimiter, $parent_links );
        }

        // Lets build the breadcrumb trail
        if ( $parent_string ) {
            $breadcrumb_trail = $parent_string . $delimiter . $post_link;
        } else {
            $breadcrumb_trail = $post_link;
        }

        if ( $post_type_link )
            $breadcrumb_trail = $post_type_link . $delimiter . $breadcrumb_trail;

        if ( $category_links )
            $breadcrumb_trail = $category_links . $breadcrumb_trail;
    }

    // Handle archives which includes category-, tag-, taxonomy-, date-, custom post type archives and author archives
    if( is_archive() )
    {
        if (    is_category()
             || is_tag()
             || is_tax()
        ) {
            // Set the variables for this section
            $term_object        = get_term( $queried_object );
            $taxonomy           = $term_object->taxonomy;
            $term_id            = $term_object->term_id;
            $term_name          = $term_object->name;
            $term_parent        = $term_object->parent;
            $taxonomy_object    = get_taxonomy( $taxonomy );
            $current_term_link  = $before . $taxonomy_object->labels->singular_name . ': ' . $term_name . $after;
            $parent_term_string = '';

            if ( 0 !== $term_parent )
            {
                // Get all the current term ancestors
                $parent_term_links = [];
                while ( $term_parent ) {
                    $term = get_term( $term_parent, $taxonomy );

                    $parent_term_links[] = sprintf( $link, esc_url( get_term_link( $term ) ), $term->name );

                    $term_parent = $term->parent;
                }

                $parent_term_links  = array_reverse( $parent_term_links );
                $parent_term_string = implode( $delimiter, $parent_term_links );
            }

            if ( $parent_term_string ) {
                $breadcrumb_trail = $parent_term_string . $delimiter . $current_term_link;
            } else {
                $breadcrumb_trail = $current_term_link;
            }

        } elseif ( is_author() ) {

            $breadcrumb_trail = __( 'Author archive for ') .  $before . $queried_object->data->display_name . $after;

        } elseif ( is_date() ) {
            // Set default variables
            $year     = $wp_the_query->query_vars['year'];
            $monthnum = $wp_the_query->query_vars['monthnum'];
            $day      = $wp_the_query->query_vars['day'];

            // Get the month name if $monthnum has a value
            if ( $monthnum ) {
                $date_time  = DateTime::createFromFormat( '!m', $monthnum );
                $month_name = $date_time->format( 'F' );
            }

            if ( is_year() ) {

                $breadcrumb_trail = $before . $year . $after;

            } elseif( is_month() ) {

                $year_link        = sprintf( $link, esc_url( get_year_link( $year ) ), $year );

                $breadcrumb_trail = $year_link . $delimiter . $before . $month_name . $after;

            } elseif( is_day() ) {

                $year_link        = sprintf( $link, esc_url( get_year_link( $year ) ),             $year       );
                $month_link       = sprintf( $link, esc_url( get_month_link( $year, $monthnum ) ), $month_name );

                $breadcrumb_trail = $year_link . $delimiter . $month_link . $delimiter . $before . $day . $after;
            }

        } elseif ( is_post_type_archive() ) {

            $post_type        = $wp_the_query->query_vars['post_type'];
            $post_type_object = get_post_type_object( $post_type );

            $breadcrumb_trail = $before . $post_type_object->labels->singular_name . $after;

        }
    }   

    // Handle the search page
    if ( is_search() ) {
        $breadcrumb_trail = __( 'Search query for: ' ) . $before . get_search_query() . $after;
    }

    // Handle 404's
    if ( is_404() ) {
        $breadcrumb_trail = $before . __( 'Error 404' ) . $after;
    }

    // Handle paged pages
    if ( is_paged() ) {
        $current_page = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : get_query_var( 'page' );
        $page_addon   = $before . sprintf( __( ' ( Page %s )' ), number_format_i18n( $current_page ) ) . $after;
    }

    $breadcrumb_output_link  = '';
    $breadcrumb_output_link .= '<div class="breadcrumb">';
    if (    is_home()
         || is_front_page()
    ) {
        // Do not show breadcrumbs on page one of home and frontpage
        if ( is_paged() ) {
            $breadcrumb_output_link .= $here_text . $delimiter;
            $breadcrumb_output_link .= '<a href="' . $home_link . '">' . $home_text . '</a>';
            $breadcrumb_output_link .= $page_addon;
        }
    } else {
        $breadcrumb_output_link .= $here_text . $delimiter;
        $breadcrumb_output_link .= '<a href="' . $home_link . '" rel="v:url" property="v:title">' . $home_text . '</a>';
        $breadcrumb_output_link .= $delimiter;
        $breadcrumb_output_link .= $breadcrumb_trail;
        $breadcrumb_output_link .= $page_addon;
    }
    $breadcrumb_output_link .= '</div><!-- .breadcrumbs -->';

    return $breadcrumb_output_link;
}
add_shortcode('custom_breadcrumbs','custom_breadcrumbs');

Display breadcrumbs code

echo do_shortcode('[custom_breadcrumbs]');
like image 155
Full Stop Avatar answered Nov 10 '22 22:11

Full Stop


Here's the basic function that hopefully should get you or someone else in the right direction:

function so_63339155_get_page_hierarchy($post = null): array
{
    // Make sure we have something
    $post = get_post($post);
    if (!$post) {
        return [];
    }

    // This will get all Post IDs of the "parent" objects
    $ancestors = get_post_ancestors($post);
    if (0 === count($ancestors)) {
        return [];
    }

    $ret = [];
    foreach ($ancestors as $postId) {
        // Grab the children for the page.
        // NOTE: This can take additional arguments such as sort order and visibility
        $ret[$postId] = get_children($postId);
    }

    return $ret;
}

Querying the site's hierarchy and getting object data for a lot of posts can be a little expensive, so you might want to check into some caching.

The above code uses the native hierarchy system for pages and should work for any CPT that is based off of the page type. It does not support taxonomy terms, that is a similar but different beast. It also does not take the home/front page on the beginning or the current page on the end, but that can be adapted pretty easily, too.

The result is an array whose keys are Post IDs for the parents and whose values are WP_Post objects of the children, so get_post() will need to be called one more time on the keys, and you'll want to call get_permalink() to get the URLs.

like image 27
Chris Haas Avatar answered Nov 11 '22 00:11

Chris Haas