- Вопрос или проблема
- Ответ или решение
- Как добавить пользовательский слаг таксономии в ссылку на произвольный тип записи (CPT) в WordPress
- Шаг 1: Регистрация произвольного типа записи
- Шаг 2: Регистрация пользовательской таксономии
- Шаг 3: Обработка плейсхолдера в URL
- Шаг 4: Настройка правил перезаписи
- Шаг 5: Подгонка хлебных крошек Yoast
- Заключение
Вопрос или проблема
Это код, который у меня есть на данный момент для добавления CPT articles
и таксономии articles-category
.
Код работает, в общем. Страницы отображаются правильно (когда я получаю к ним доступ напрямую):
articles/
articles/categ-slug/
articles/categ-slug/post-slug/
Проблема возникает, когда постоянные ссылки генерируются автоматически (например, хлебные крошки Yoast)
<span typeof="v:Breadcrumb">
<a href="https://wordpress.stackexchange.com/questions/204681/example.com" rel="v:url" property="v:title">Пример</a> /
<span rel="v:child" typeof="v:Breadcrumb"><a href="example.com/articles/%articles-category%/" rel="v:url" property="v:title">Статьи</a> /
<span rel="v:child" typeof="v:Breadcrumb"><a href="example.com/articles/categ-slug/" rel="v:url" property="v:title">Имя категории</a> /
<span class="breadcrumb_last">Имя поста</span></span></span></span>
Обратите внимание на example.com/articles/
%articles-category%/, где должно быть просто
example.com/articles/
Что не так с кодом и как я могу заставить его работать?
function custom_post_articles() {
$labels = array(
// метки
);
$args = array(
'labels' => $labels,
'public' => true,
'menu_position' => 5,
'supports' => array( 'title', 'editor', 'thumbnail', 'excerpt', 'comments' ),
'has_archive' => true,
'hierarchical' => true,
'rewrite' => array('slug' => 'articles/%articles-category%','with_front' => false),
'query_var' => true,
//'rewrite' => true,
//'publicly_queryable' => false,
);
register_post_type( 'articles', $args );
}
add_action( 'init', 'custom_post_articles' );
function my_taxonomies_product() {
$labels = array(
//метки
);
$args = array(
'labels' => $labels,
'hierarchical' => true,
'public' => true,
'query_var' => 'articles-category',
'rewrite' => array('slug' => 'articles' ),
'_builtin' => false,
);
register_taxonomy( 'articles-category', 'articles', $args );
}
add_action( 'init', 'my_taxonomies_product', 0 );
add_filter('post_link', 'articles_category_permalink', 1, 3);
add_filter('post_type_link', 'articles_category_permalink', 1, 3);
function articles_category_permalink($permalink, $post_id, $leavename) {
if (strpos($permalink, '%articles-category%') === FALSE) return $permalink;
// Получить пост
$post = get_post($post_id);
if (!$post) return $permalink;
// Получить термины таксономии
$terms = wp_get_object_terms($post->ID, 'articles-category');
if (!is_wp_error($terms) && !empty($terms) && is_object($terms[0]))
$taxonomy_slug = $terms[0]->slug;
else $taxonomy_slug = 'no-category';
return str_replace('%articles-category%', $taxonomy_slug, $permalink);
}
Я решил это следующим образом:
Регистрация пользовательского типа записи:
function custom_post_articles() {
$labels = array(
'name' => _x( 'Статьи', 'имя общего типа записи', 'textdomain' ),
'singular_name' => _x( 'Статья', 'имя единственного типа записи', 'textdomain' ),
// и т. д.
);
$args = array(
'labels' => $labels,
'public' => true,
'menu_position' => 5, // Ниже постов.
'menu_icon' => 'dashicons-megaphone', // https://developer.wordpress.org/resource/dashicons/
'capability_type' => 'post',
'hierarchical' => false, // Ложь, как пост, истина, как страница.
'has_archive' => true, // Ложь, как страница, истина, как пост.
'rewrite' => array(
'slug' => 'articles/%articles_tax%',
'with_front' => false
),
'supports' => array(
'title',
'editor',
'author',
'thumbnail'
)
);
register_post_type( 'articles', $args );
}
add_action( 'init', 'custom_post_articles' );
Регистрация пользовательской таксономии:
function taxonomies_product() {
$labels = array(
// метки
);
$args = array(
'labels' => $labels,
'public' => true,
'hierarchical' => true, // Ложь, как тег, истина, как категория.
'rewrite' => array(
'slug' => 'articles', // Могут содержать строчные буквы и символ нижнего подчеркивания (макс. 32 знака). По умолчанию: $taxonomy.
'with_front' => false,
'hierarchical' => true // Позволить иерархические URL.
)
);
register_taxonomy( 'articles_tax', 'articles', $args );
}
add_action( 'init', 'taxonomies_product' );
RewriteRule для структуры URL статей:
function rewrite_rules_articles( $rules ) {
$new = array();
$new[ 'articles/([^/]+)/(.+)/?$' ] = 'index.php?articles=$matches[2]';
$new[ 'articles/(.+)/?$' ] = 'index.php?articles_tax=$matches[1]';
return array_merge( $new, $rules ); // Поместите эти правила первыми.
}
add_filter( 'rewrite_rules_array', 'rewrite_rules_articles' );
Замените заполнитель в URL на термин таксономии:
function handle_placeholder_term_slug( $url, $post ) {
if ( $post->post_type == 'articles' ) {
if ( $cats = get_the_terms( $post->ID, 'articles_tax' ) ) {
$url = str_replace( '%articles_tax%', current( $cats )->slug, $url );
}
}
return $url;
}
add_filter( 'post_type_link', 'handle_placeholder_term_slug', 10, 2 );
Удалить заполнитель из хлебных крошек Yoast:
function remove_placeholder_yoast_crumb( $link_output, $link ) {
if ( $link[ 'text' ] == 'Статьи' ) {
$link_output = str_replace( '/%articles_tax%', '', $link_output );
}
/* в случае многоязычного сайта
if ( in_array( $link[ 'text' ], array( 'Статьи', 'Artikel', 'Articoli' ) ) ) {
$link_output = str_replace( '/%articles_tax%', '', $link_output );
}
*/
return $link_output;
}
add_filter( 'wpseo_breadcrumb_single_link', 'remove_placeholder_yoast_crumb', 10 ,2 );
Ответ или решение
Как добавить пользовательский слаг таксономии в ссылку на произвольный тип записи (CPT) в WordPress
В этой статье мы рассмотрим, как правильно настроить слаг пользовательской таксономии в URL вашего произвольного типа записи (CPT) в WordPress, на примере CPT "articles" и таксономии "articles-category". Эта цель требует тщательной настройки регистрации постов и таксономий, а также обработки маршрутизации. Вы уже проделали неплохую работу, но есть определенные аспекты, которые мы можем доработать для достижения желаемого результата.
Шаг 1: Регистрация произвольного типа записи
Начнем с регистрации CPT "articles". Обратите внимание, как мы настраиваем перезапись с помощью плейсхолдеров.
function custom_post_articles() {
$labels = array(
'name' => _x('Articles', 'post type general name', 'textdomain'),
'singular_name' => _x('Article', 'post type singular name', 'textdomain'),
// Другие метки...
);
$args = array(
'labels' => $labels,
'public' => true,
'menu_position' => 5,
'supports' => array('title', 'editor', 'thumbnail'),
'has_archive' => true,
'rewrite' => array(
'slug' => 'articles/%articles-category%', // Заходим в слаг с плейсхолдером
'with_front' => false,
),
);
register_post_type('articles', $args);
}
add_action('init', 'custom_post_articles');
Шаг 2: Регистрация пользовательской таксономии
Следующим шагом будет регистрация таксономии "articles-category". Обратите внимание, что в опции rewrite
вы задаете слаг без плейсхолдеров.
function my_taxonomies_product() {
$labels = array(
// Метки таксономии...
);
$args = array(
'labels' => $labels,
'public' => true,
'hierarchical' => true,
'rewrite' => array(
'slug' => 'articles', // Здесь слаг для таксономии
'with_front' => false,
'hierarchical' => true, // Это позволить создавать иерархические URL
),
);
register_taxonomy('articles-category', 'articles', $args);
}
add_action('init', 'my_taxonomies_product');
Шаг 3: Обработка плейсхолдера в URL
Теперь необходимо заменить плейсхолдер в URL фактическим значением таксономии при генерации ссылок. Это делается с помощью фильтров.
add_filter('post_type_link', 'articles_category_permalink', 1, 3);
function articles_category_permalink($permalink, $post_id, $leavename) {
if (strpos($permalink, '%articles-category%') === FALSE) return $permalink;
// Получаем пост
$post = get_post($post_id);
if (!$post) return $permalink;
// Получаем термины таксономии
$terms = wp_get_object_terms($post->ID, 'articles-category');
if (!is_wp_error($terms) && !empty($terms) && is_object($terms[0]))
$taxonomy_slug = $terms[0]->slug;
else
$taxonomy_slug = 'no-category'; // Значение по умолчанию
return str_replace('%articles-category%', $taxonomy_slug, $permalink);
}
Шаг 4: Настройка правил перезаписи
Чтобы ваши ссылки корректно работали, обновите правила перезаписи. Это позволит указать, как обрабатывать запрашиваемые URL.
function rewrite_rules_articles($rules) {
$new = array();
$new['articles/([^/]+)/(.+)/?$'] = 'index.php?articles=$matches[2]&articles-category=$matches[1]'; // Установите новые правила
$new['articles/(.+)/?$'] = 'index.php?articles-category=$matches[1]'; // Для категории
return array_merge($new, $rules); // Ставим такие правила первыми
}
add_filter('rewrite_rules_array', 'rewrite_rules_articles');
Шаг 5: Подгонка хлебных крошек Yoast
Часто плагины, такие как Yoast SEO, автоматически генерируют хлебные крошки на основе структуры URL, что может привести к появлению плейсхолдеров. Обработайте вывод хлебных крошек для удаления ненужных элементов.
add_filter('wpseo_breadcrumb_single_link', 'remove_placeholder_yoast_crumb', 10 ,2);
function remove_placeholder_yoast_crumb($link_output, $link) {
if ($link['text'] == 'Articles') {
$link_output = str_replace('/%articles-category%', '', $link_output);
}
return $link_output;
}
Заключение
Теперь, когда вы правильно настроили и зарегистрировали ваш CPT и таксономию, а также обработали перезапись URL, ваш сайт будет корректно генерировать ссылки с пользовательскими слагами для таксономий. Не забудьте обновить постоянные ссылки в админке WordPress (Настройки → Постоянные ссылки), чтобы изменения вступили в силу. Эта инструкция должна помочь вам полностью решить вашу проблему с плейсхолдерами в URL.
Сложности бывают, но результат стоит того. Удачи в ваших дальнейших разработках!