Как добавить пользовательский слаг таксономии в пермалинк CPT?

Вопрос или проблема

Это код, который у меня есть на данный момент для добавления 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.

Сложности бывают, но результат стоит того. Удачи в ваших дальнейших разработках!

Оцените материал
Добавить комментарий

Капча загружается...