Хлебные крошки с произвольным типом записи без плагина

6 окт. 2015 г., 12:57:05
Просмотры: 32K
Голосов: 1

Я использовал следующую функцию для хлебных крошек на всех сайтах до настоящего времени, но сегодняшний сайт имеет 3 произвольных типа записей, и клиент хочет, чтобы хлебные крошки работали правильно. Например, вместо "главная / вина / naire blanco" мы получаем только "главная / / naire blanco".

function the_breadcrumb() {
        echo '<ol class="breadcrumb" itemprop="breadcrumb">';
    if (!is_home()) {
        echo '<li><a href="';
        echo get_option('home');
        echo '">';
        echo 'Главная';
        echo '</a></li>';
        if (is_category() || is_single() || is_post_type()) {
            echo '<li>';
            the_category(' </li><li> ');
            echo get_post_type(' </li><li> ');
            if (is_single()) {
                echo '</li><li>';
                the_title();
                echo '</li>';
            }
        } elseif (is_page()) {
            if($post->post_parent){
                $anc = get_post_ancestors( $post->ID );

                foreach ( $anc as $ancestor ) {
                    $output = $output . '<li><a href="'.get_permalink($ancestor).'" title="'.get_the_title($ancestor).'">'.get_the_title($ancestor).'</a></li> ';
                }
                echo $output;
                echo '<strong title="'.$title.'"> '.$title.'</strong>';
            } else {
                echo '<li><a class="active" href="';
                echo the_permalink();
                echo '">';
        echo the_title();
        echo '</a></li>';
            }
        }
    }
    elseif (is_tag()) {single_tag_title();}
    elseif (is_day()) {echo"<li>Архив за "; the_time('F jS, Y'); echo'</li>';}
    elseif (is_month()) {echo"<li>Архив за "; the_time('F, Y'); echo'</li>';}
    elseif (is_year()) {echo"<li>Архив за "; the_time('Y'); echo'</li>';}
    elseif (is_author()) {echo"<li>Архив автора"; echo'</li>';}
    elseif (isset($_GET['paged']) && !empty($_GET['paged'])) {echo "<li>Архивы блога"; echo'</li>';}
    elseif (is_search()) {echo"<li>Результаты поиска"; echo'</li>';}
    echo '</ol>';
}

Как видно из кода, я попытался добавить || is_post_type() после is_category() || is_single() с echo get_post_type(), но это не дало никакого результата.

Буду признателен за помощь.

Спасибо

0
Все ответы на вопрос 3
1
11

Основная проблема большинства функций для хлебных крошек заключается в том, что они полагаются на глобальный объект $post на всех страницах. Глобальный объект $post не только крайне ненадежен (см. мою статью здесь), но он также может не содержать нужных нам данных, даже если сам объект не был скомпрометирован.

Глобальный объект $post на архивных страницах (включая категории, метки, даты, таксономии, авторов и архивы пользовательских типов записей) содержит первую запись в цикле до начала самого цикла. Нет гарантии, что первая запись будет из выбранного архива (страницы, на которой вы находитесь), что означает, что информация может быть неверной, даже если глобальный объект $post не был скомпрометирован. Ситуации, когда первая запись может не относиться к выбранному архиву, включают кастомные закрепленные записи и фильтр the_posts.

Я недавно переписал свою старую функцию для хлебных крошек, которая использует объект $GLOBALS['wp_the_query'] и сохраненный в нем queried object. Таким образом, мы получаем 99.999% надежные хлебные крошки, не зависящие от глобального объекта $post или каких-либо скомпрометированных данных.

Вот сама функция: (Требуется PHP 5.4+. Можете свободно изменять по необходимости)

function get_hansel_and_gretel_breadcrumbs()
{
    // Устанавливаем переменные для дальнейшего использования
    $here_text        = __( 'Вы находитесь здесь!' );
    $home_link        = home_url('/');
    $home_text        = __( 'Главная' );
    $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; ';              // Разделитель между крошками
    $before           = '<span class="current">'; // Тег перед текущей крошкой
    $after            = '</span>';                // Тег после текущей крошки
    $page_addon       = '';                       // Добавляет номер страницы, если запрос разбит на страницы
    $breadcrumb_trail = '';
    $category_links   = '';

    /** 
     * Устанавливаем собственную переменную $wp_the_query. Не используем глобальную версию 
     * из-за ненадежности
     */
    $wp_the_query   = $GLOBALS['wp_the_query'];
    $queried_object = $wp_the_query->get_queried_object();

    // Обрабатываем одиночные записи, включая страницы, посты и вложения
    if ( is_singular() ) 
    {
        /** 
         * Устанавливаем собственную переменную $post. Не используем глобальную версию 
         * из-за ненадежности. Устанавливаем $post_object в $GLOBALS['wp_the_query']
         */
        $post_object = sanitize_post( $queried_object );

        // Устанавливаем переменные
        $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 ) 
        {
            // Получаем категории поста
            $categories = get_the_category( $post_id );
            if ( $categories ) {
                // Берем первую категорию
                $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 );
        }

        // Получаем родительские посты, если $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 );
        }

        // Собираем цепочку хлебных крошек
        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;
    }

    // Обрабатываем архивы, включая категории, метки, таксономии, даты, пользовательские типы записей и архивы авторов
    if( is_archive() )
    {
        if (    is_category()
             || is_tag()
             || is_tax()
        ) {
            // Устанавливаем переменные для этого раздела
            $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 )
            {
                // Получаем всех предков текущего элемента таксономии
                $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 = __( 'Архив автора: ') .  $before . $queried_object->data->display_name . $after;

        } elseif ( is_date() ) {
            // Устанавливаем стандартные переменные
            $year     = $wp_the_query->query_vars['year'];
            $monthnum = $wp_the_query->query_vars['monthnum'];
            $day      = $wp_the_query->query_vars['day'];

            // Получаем название месяца, если $monthnum имеет значение
            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;

        }
    }   

    // Обрабатываем страницу поиска
    if ( is_search() ) {
        $breadcrumb_trail = __( 'Результаты поиска для: ' ) . $before . get_search_query() . $after;
    }

    // Обрабатываем 404 ошибки
    if ( is_404() ) {
        $breadcrumb_trail = $before . __( 'Ошибка 404' ) . $after;
    }

    // Обрабатываем страницы с пагинацией
    if ( is_paged() ) {
        $current_page = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : get_query_var( 'page' );
        $page_addon   = $before . sprintf( __( ' (Страница %s )' ), number_format_i18n( $current_page ) ) . $after;
    }

    $breadcrumb_output_link  = '';
    $breadcrumb_output_link .= '<div class="breadcrumb">';
    if (    is_home()
         || is_front_page()
    ) {
        // Не показываем хлебные крошки на первой странице главной и фронтпейджа
        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;
}

Вы можете вызвать её следующим образом

echo get_hansel_and_gretel_breadcrumbs();

в нужном месте

Эта функция также корректно обрабатывает пользовательские типы записей.

23 мар. 2016 г. 11:38:29
Комментарии

Ваш код работает отлично, но Google скоро прекратит поддержку разметки data-vocabulary (https://webmasters.googleblog.com/2020/01/data-vocabulary.html), и код начнет выдавать ошибки в Search Console. Я изменил его, чтобы сделать совместимым с schema.org (https://schema.org/BreadcrumbList). Я почти закончил, но не могу реализовать значение для itemprop="position". Я новичок в сообществе StackExchange и пока не знаю, как вставлять код, поэтому использовал gist, чтобы показать свой код: https://gist.github.com/Marinski/4cefcbb7ded15582c4adfa0dc1c53946. Есть ли у вас предложения, как это сделать? Спасибо.

Marinski Marinski
21 мая 2020 г. 22:45:26
1

Отлично! Код из принятого ответа (от Pieter Goosen) работает.

Примечание: Я добавил небольшую дополнительную задачу. Сделайте проверку существования функции перед её вызовом, вот так:

<?php 
   if(function_exists('get_hansel_and_gretel_breadcrumbs')): 
      echo get_hansel_and_gretel_breadcrumbs();
   endif;
?>

Дополнительно, я сохранил эту функцию в файл с именем breadcrumbs.php в корневой папке проекта и подключил его в файл functions.php с помощью include_once('breadcrumbs.php'); для лучшей организации кода.

8 мая 2017 г. 12:12:02
Комментарии

также можно обернуть саму функцию в if (!function_exists('get_hansel_and_gretel_breadcrumbs')) на случай, если другие плагины или тема используют такую же функцию/имя.

MikeiLL MikeiLL
5 сент. 2017 г. 22:45:25
1
function get_hansel_and_gretel_breadcrumbs()
{
    // Установка переменных для последующего использования
    $here_text        = __( 'Вы находитесь здесь!' );
    $home_link        = home_url('/');
    $home_text        = __( 'Главная' );
    $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; ';              // Разделитель между элементами
    $before           = '<span class="current">'; // Тег перед текущим элементом
    $after            = '</span>';                // Тег после текущего элемента
    $page_addon       = '';                       // Добавляет номер страницы, если запрос разбит на страницы
    $breadcrumb_trail = '';
    $category_links   = '';

    /** 
     * Устанавливаем свою переменную $wp_the_query. Не используем глобальную переменную 
     * из-за проблем с надежностью
     */
    $wp_the_query   = $GLOBALS['wp_the_query'];
    $queried_object = $wp_the_query->get_queried_object();

    // Обработка одиночных записей, включая страницы, записи и вложения
    if ( is_singular() ) 
    {
        /** 
         * Устанавливаем свою переменную $post. Не используем глобальную переменную 
         * из-за проблем с надежностью. Устанавливаем $post_object в $GLOBALS['wp_the_query']
         */
        $post_object = sanitize_post( $queried_object );

        // Установка переменных 
        $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 ) 
        {
            // Получаем категории записи
            $categories = get_the_category( $post_id );
            if ( $categories ) {
                // Берем первую категорию
                $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 );
        }

        // Получаем родительские записи, если $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 );
        }

        // Формируем цепочку навигации
        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 . $delimiter . $breadcrumb_trail;
    }

    // Обработка архивов, включая категории, метки, таксономии, даты, пользовательские типы записей и архивы авторов
    if( is_archive() )
    {
        if (    is_category()
             || is_tag()
             || is_tax()
        ) {
            // Установка переменных для этого раздела
            $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 )
            {
                // Получаем всех предков текущего элемента таксономии
                $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 = __( 'Архив автора: ') .  $before . $queried_object->data->display_name . $after;

        } elseif ( is_date() ) {
            // Установка переменных по умолчанию
            $year     = $wp_the_query->query_vars['year'];
            $monthnum = $wp_the_query->query_vars['monthnum'];
            $day      = $wp_the_query->query_vars['day'];

            // Получаем название месяца, если $monthnum имеет значение
            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;

        }
    }   

    // Обработка страницы поиска
    if ( is_search() ) {
        $breadcrumb_trail = __( 'Результаты поиска для: ' ) . $before . get_search_query() . $after;
    }

    // Обработка 404 ошибки
    if ( is_404() ) {
        $breadcrumb_trail = $before . __( 'Ошибка 404' ) . $after;
    }

    // Обработка страниц с пагинацией
    if ( is_paged() ) {
        $current_page = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : get_query_var( 'page' );
        $page_addon   = $before . sprintf( __( ' (Страница %s)' ), number_format_i18n( $current_page ) ) . $after;
    }

    $breadcrumb_output_link  = '';
    $breadcrumb_output_link .= '<div class="breadcrumb">';
    if (    is_home()
         || is_front_page()
    ) {
        // Не показывать хлебные крошки на первой странице главной или лендинга
        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;
}
12 нояб. 2018 г. 11:35:35
Комментарии

Можете объяснить текстом, почему это будет работать, что вы сделали и т.д.?

kero kero
12 нояб. 2018 г. 11:42:32