Смешивание структур пользовательского типа записей и таксономии

25 июн. 2011 г., 18:03:17
Просмотры: 26.2K
Голосов: 32

В основном я хочу создать глоссарий, используя пользовательские типы записей, и у меня есть проблемы с настройкой ЧПУ так, как я хочу. Мне нужно следующее:

Основной URL глоссария: http://example.com/glossary/

Термины глоссария, начинающиеся с буквы A: http://example.com/glossary/a/

URL для отдельного термина глоссария: http://example.com/glossary/a/atomic/

Я фактически достиг этого, используя код ниже, но я уверен, что это очень неудобный способ, и я знаю, что где-то есть сбои, так как при просмотре страниц вызываются неправильные шаблоны. За исключением http://example.com/glossary/, где вызывается archive-sumo-glossary-term.php как ожидалось, два других просто активируют index.php в моей теме.

Вот код (functions.php в теме):

add_action('init', 'create_glossary');
function create_glossary()
{
    register_post_type
    (
        'sumo-glossary-term',
        array
        (
            'labels' => array
            (
                'name' => _x('Термины глоссария', 'общее название типа записи'),
                'singular_name' => _x('Термин глоссария', 'единственное число типа записи')
                # И так далее...
            ),
            'supports' => array('title', 'editor', 'thumbnail'),
            'public' => true,
            'rewrite' => array
            (
                'slug' => 'glossary',
                'with_front' => false

            ),
            'query_var' => 'glossary-term',
            'has_archive' => true
        )
    );

    register_taxonomy
    (
        'sumo-glossary-letter',
        'sumo-glossary-term',
        array
        (
            'hierarchical' => true,
            'labels' => array
            (
                'name' => _x('Буквы', 'общее название таксономии'),
                'singular_name' => _x('Буква', 'единственное число таксономии')
                # И так далее...
            ),
            'show_ui' => true,
            'query_var' => 'glossary-letter',
            'rewrite' => false
        )
    );
}

add_filter('post_type_link', 'glossary_term_permalink', 10, 4);
function glossary_term_permalink($post_link, $post, $leavename, $sample)
{
    if ($post->post_type == 'sumo-glossary-term')
    {
        $permalink = str_replace('glossary/', 'glossary/' . $post->post_name[0] . '/', $post_link);
    }
    return $permalink;
}

add_rewrite_rule('^glossary/([^/]*)?$','index.php?glossary-letter=$matches[1]','top');
add_rewrite_rule('^glossary/([^/]*)/([^/]*)?$','index.php?glossary-term=$matches[2]','top');
0
Все ответы на вопрос 2
8
35

Вы всегда можете переопределить шаблон, который будет вызываться с помощью фильтра template_include или родственного ему, но это может скрыть более глубокие проблемы с пользовательскими архивами.

Как я понимаю, вы хотите использовать следующую структуру:

  • /glossary/ должна быть страницей архива для всех записей типа sumo-glossary-term
  • /glossary/[буква]/ должна быть страницей архива для записей с термином таксономии [буква] в таксономии sumo-glossary-letter
  • /glossary/[буква]/[название-термина]/ должна быть отдельной записью типа sumo-glossary-term

Это означает, что первая будет загружать шаблон archive-sumo-glossary-term.php, вторая — taxonomy-sumo-glossary-letter.php, а третья — single-sumo-glossary-term.php.

Я добился этого в WordPress 3.2, явно указав слаг для перезаписи таксономии, а также слаг для перезаписи и архивный слаг для типа записи, без других правил перезаписи. Кроме того, я зарегистрировал таксономию первой, а тип записи — после неё, чтобы приоритеты были правильными (в противном случае URL вида /glossary/f/page/2 ведёт на термин глоссария page вместо 2-й страницы буквы f).

add_action('init', 'create_glossary');
function create_glossary()
{
    // Регистрация таксономии для букв глоссария
    register_taxonomy
    (
        'sumo-glossary-letter',
        array(),
        array
        (
            'hierarchical' => true,
            'labels' => array
            (
                'name' => _x('Буквы', 'общее название таксономии'),
                'singular_name' => _x('Буква', 'название таксономии в единственном числе')
                # И так далее...
            ),
            'show_ui' => true,
            'query_var' => 'glossary-letter',
            'rewrite' => array(
                'slug' => 'glossary',
            ),
        )
    );

    // Регистрация типа записи для терминов глоссария
    register_post_type
    (
        'sumo-glossary-term',
        array
        (
            'labels' => array
            (
                'name' => _x('Термины глоссария', 'общее название типа записи'),
                'singular_name' => _x('Термин глоссария', 'название типа записи в единственном числе')
                # И так далее...
            ),
            'supports' => array('title', 'editor', 'thumbnail'),
            'public' => true,
            'rewrite' => array
            (
                'slug' => 'glossary/%sumo-glossary-letter%',
                'with_front' => false
            ),
            'query_var' => 'glossary-term',
            'has_archive' => 'glossary',
            'taxonomies' => array( 'sumo-glossary-letter' ),
        )
    );
}

// Фильтр для формирования правильных постоянных ссылок терминов глоссария
add_filter('post_type_link', 'glossary_term_permalink', 10, 4);
function glossary_term_permalink($post_link, $post, $leavename, $sample)
{
    if ( false !== strpos( $post_link, '%sumo-glossary-letter%' ) ) {
        $glossary_letter = get_the_terms( $post->ID, 'sumo-glossary-letter' );
        $post_link = str_replace( '%sumo-glossary-letter%', array_pop( $glossary_letter )->slug, $post_link );
    }
    return $post_link;
}
9 июл. 2011 г. 15:43:12
Комментарии

Попробую завтра и посмотрю, сработает ли это, а потом отпишусь здесь. Спасибо!

maryisdead maryisdead
9 июл. 2011 г. 19:37:47

Ок, не совсем "завтра"... Сработало, почти идеально! Спасибо!

Не работает только /glossary/. Выдает 404 (archive-sumo-glossary-term.php настроен). Есть идеи? Должен сказать, что я застрял на WP 3.0.1, и, возможно, это проблема версии. Придется протестировать снова, когда смогу обновиться.

В любом случае, большая часть работает, и сейчас мне не критично нужен /glossary/, можно просто перенаправлять на букву A. Еще раз спасибо!

maryisdead maryisdead
16 июл. 2011 г. 17:40:44

Привет @maryisdead, у меня была точно такая же проблема, и я пришел к такому же решению, но остался с той же проблемой - как заставить /glossary использовать шаблон archive-glossery.php? Я только что нашел ответ - используй 'has_archive' => 'glossary' вместо has_archive => true

Только заметил, что у Яна в ответе именно так, а у тебя в исходном коде не так - ты обновил эту часть? У меня заработало сразу после этого изменения

Jeff Jeff
9 февр. 2012 г. 02:01:11

Привет, Джефф! Да, обновил эту часть. Только что проверил снова, всё ещё не работает. Установка WordPress в данном случае не обновлена (3.0.1), так что, возможно, корень проблемы именно в этом.

maryisdead maryisdead
11 февр. 2012 г. 15:50:20

Та же проблема здесь, использую WP 3.2.1. Всё ещё нет решения?

Richard B Richard B
5 мар. 2012 г. 17:42:32

Код всё ещё актуален — я по-прежнему использую его как основное решение для достижения такой структуры.

Один вопрос: если создана запись, к которой не присвоен термин таксономии (так что URL будет вида customposttypeslug/postslug) — я получаю ошибку 404. Есть ли способ (вероятно, через правила постоянных ссылок) добиться, чтобы это тоже работало?

Gerben van Dijk Gerben van Dijk
27 мая 2014 г. 12:12:52

РАБОТАЕТ ИДЕАЛЬНО! В моём случае ключевым моментом оказался порядок регистрации таксономии и CPT.

FullStack Alex FullStack Alex
19 сент. 2019 г. 06:50:51

Это по-прежнему отлично работает. Я создаю записи программно, и фильтр post_type_link срабатывает при использовании wp_insert_post(). Но мне удалось обойти это, задавая guid при выполнении wp_insert_post().

Daan van den Bergh Daan van den Bergh
2 мар. 2025 г. 16:07:32
Показать остальные 3 комментариев
1

Я лично не использовал это, но вам может быть полезно взглянуть на "add_rewrite_rule".

http://codex.wordpress.org/Rewrite_API/add_rewrite_rule

Также не забудьте сохранить постоянные ссылки после внесения изменений.

29 июн. 2011 г. 21:57:41
Комментарии

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

maryisdead maryisdead
30 июн. 2011 г. 07:25:18