Смешивание структур пользовательского типа записей и таксономии
В основном я хочу создать глоссарий, используя пользовательские типы записей, и у меня есть проблемы с настройкой ЧПУ так, как я хочу. Мне нужно следующее:
Основной 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');
Вы всегда можете переопределить шаблон, который будет вызываться с помощью фильтра 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;
}

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

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

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

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

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

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

Я лично не использовал это, но вам может быть полезно взглянуть на "add_rewrite_rule".
http://codex.wordpress.org/Rewrite_API/add_rewrite_rule
Также не забудьте сохранить постоянные ссылки после внесения изменений.
