Добавление категорий в пользовательский тип записи в постоянной ссылке

28 мая 2012 г., 18:33:48
Просмотры: 31.9K
Голосов: 23

Я знаю, что люди уже задавали этот вопрос и дошли до добавления пользовательского типа записи и перезаписи для постоянной ссылки.

Проблема в том, что у меня есть 340 существующих категорий, которые я хотел бы продолжать использовать. Раньше я мог видеть /category/subcategory/postname

Теперь у меня есть слаг customposttype/postname. Выбранная категория больше не отображается в постоянной ссылке... Я не менял настройки постоянных ссылок в админке.

Может быть, я что-то упускаю или нужно что-то добавить в этот код?

function jcj_club_post_types() {
    register_post_type( 'jcj_club', array(
        'labels' => array(
            'name' => __( 'Джаз-клубы' ),
            'singular_name' => __( 'Джаз-клуб' ),
            'add_new' => __( 'Добавить новый' ),
            'add_new_item' => __( 'Добавить новый джаз-клуб' ),
            'edit' => __( 'Редактировать' ),
            'edit_item' => __( 'Редактировать джаз-клубы' ),
            'new_item' => __( 'Новый джаз-клуб' ),
            'view' => __( 'Просмотреть джаз-клуб' ),
            'view_item' => __( 'Просмотреть джаз-клуб' ),
            'search_items' => __( 'Поиск джаз-клубов' ),
            'not_found' => __( 'Джаз-клубы не найдены' ),
            'not_found_in_trash' => __( 'В корзине джаз-клубы не найдены' ),
            'parent' => __( 'Родительский джаз-клуб' ),
        ),
        'public' => true,
        'show_ui' => true,
        'publicly_queryable' => true,
        'exclude_from_search' => false,
        'menu_position' => 5,
        'query_var' => true,
        'supports' => array( 
            'title',
            'editor',
            'comments',
            'revisions',
            'trackbacks',
            'author',
            'excerpt',
            'thumbnail',
            'custom-fields',
        ),
        'rewrite' => array( 'slug' => 'jazz-clubs-in', 'with_front' => true ),
        'taxonomies' => array( 'category','post_tag'),
        'can_export' => true,
    )
);
2
Комментарии

это может быть глупый вопрос, но вы сбрасывали свои перезаписи?

kristina childs kristina childs
20 дек. 2012 г. 00:45:33

Недавно столкнулся с этой проблемой. Решено! #188834

maheshwaghmare maheshwaghmare
20 мая 2015 г. 10:02:34
Все ответы на вопрос 4
6
16

При добавлении пользовательских правил перезаписи (rewrite rules) для типов записей необходимо учитывать два ключевых момента:

Правила перезаписи

Это происходит при генерации правил перезаписи в файле wp-includes/rewrite.php, в методе WP_Rewrite::rewrite_rules(). WordPress позволяет фильтровать правила перезаписи для отдельных элементов, таких как записи, страницы и различные типы архивов. Там, где вы видите posttype_rewrite_rules, часть posttype должна быть заменена на имя вашего пользовательского типа записи. Альтернативно можно использовать фильтр post_rewrite_rules, главное не перезаписать стандартные правила для обычных записей.

Далее нам понадобится функция для генерации правил перезаписи:

// добавляем новую структуру постоянных ссылок к правилам перезаписи
add_filter( 'posttype_rewrite_rules', 'add_permastruct' );

function add_permastruct( $rules ) {
    global $wp_rewrite;

    // задаем желаемую структуру постоянных ссылок
    $struct = '/%category%/%year%/%monthnum%/%postname%/';

    // используем функцию WordPress для генерации правил перезаписи
    $rules = $wp_rewrite->generate_rewrite_rules(
        $struct,       // структура постоянных ссылок
        EP_PERMALINK,  // Маска конечной точки: добавляет правила для конечных точек отдельных записей (страницы комментариев и т.д.)
        false,         // Пагинация: добавлять ли правила для разбивки на страницы (например, для архивов) - здесь не нужно
        true,          // Ленты: добавлять ли правила для RSS-лент
        true,          // Для комментариев: должны ли правила лент относиться к комментариям записи
        false,         // Обход директорий: генерировать ли правила для каждого сегмента структуры, разделенного '/'. Всегда false, иначе правила будут слишком жадными
        true           // Добавлять пользовательские конечные точки
    );

    return $rules;
}

Основной момент, на который стоит обратить внимание при настройке - это параметр 'Walk directories' (Обход директорий). Он генерирует правила перезаписи для каждого сегмента структуры и может вызвать несоответствия. Когда WordPress обрабатывает URL, правила проверяются сверху вниз, и первое совпадение определяет дальнейшую обработку. Например, для структуры /%category%/%postname%/ с включенным обходом будут созданы правила как для /%category%/%postname%/, так и для /%category%/, что приведет к избыточным совпадениям. Если это произойдет слишком рано, возникнут проблемы.

Постоянные ссылки

Эта функция преобразует структуру постоянных ссылок (например, '/%year%/%monthnum%/%postname%/') в реальный URL.

Следующий код представляет упрощенный вариант функции get_permalink() из файла wp-includes/link-template.php. Постоянные ссылки для пользовательских типов записей генерируются функцией get_post_permalink(), которая является упрощенной версией get_permalink(). get_post_permalink() фильтруется через post_type_link, что позволяет нам создать собственную структуру.

// обрабатываем сгенерированные ссылки
add_filter( 'post_type_link', 'custom_post_permalink', 10, 4 );

function custom_post_permalink( $permalink, $post, $leavename, $sample ) {

    // выполняем наши действия только для pretty permalinks
    // и только для нужного типа записи
    if ( $post->post_type == 'posttype' && get_option( 'permalink_structure' ) ) {

        // задаем желаемую структуру постоянных ссылок
        // и заменяем плейсхолдеры реальными данными

        $struct = '/%category%/%year%/%monthnum%/%postname%/';

        $rewritecodes = array(
            '%category%',
            '%year%',
            '%monthnum%',
            '%postname%'
        );

        // получаем данные
        $terms = get_the_terms($post->ID, 'category');
        $unixtime = strtotime( $post->post_date );

        // код из get_permalink()
        $category = '';
        if ( strpos($permalink, '%category%') !== false ) {
            $cats = get_the_category($post->ID);
            if ( $cats ) {
                usort($cats, '_usort_terms_by_ID'); // сортировка по ID
                $category = $cats[0]->slug;
                if ( $parent = $cats[0]->parent )
                    $category = get_category_parents($parent, false, '/', true) . $category;
            }
            // используем рубрику по умолчанию, если не задана явно
            if ( empty($category) ) {
                $default_category = get_category( get_option( 'default_category' ) );
                $category = is_wp_error( $default_category ) ? '' : $default_category->slug;
            }
        }

        $replacements = array(
            $category,
            date( 'Y', $unixtime ),
            date( 'm', $unixtime ),
            $post->post_name
        );

        // формируем окончательную ссылку
        $permalink = home_url( str_replace( $rewritecodes, $replacements, $struct ) );
        $permalink = user_trailingslashit($permalink, 'single');
    }

    return $permalink;
}

Это упрощенный пример для создания пользовательских правил перезаписи и постоянных ссылок. Он не отличается гибкостью, но дает основу для дальнейшей работы.

Обходной путь

Я создал плагин, который позволяет определять структуру постоянных ссылок для любых пользовательских типов записей. Подобно тому, как %category% работает для обычных записей, мой плагин поддерживает %название_таксономии% для любых пользовательских таксономий, например %club%.

Плагин работает как с иерархическими, так и с неиерархическими таксономиями.

http://wordpress.org/extend/plugins/wp-permastructure/

20 дек. 2012 г. 15:19:58
Комментарии

плагин отличный, но не могли бы вы объяснить, как исправить проблему в вопросе без вашего плагина?

Eugene Manuilov Eugene Manuilov
20 дек. 2012 г. 15:39:09

Я согласен, что здорово, что есть плагин для решения этой проблемы (у меня он в закладках и первым пришел на ум при этом вопросе), но ответ выиграл бы от краткого описания сути проблемы и того, как плагин ее решает. :)

Rarst Rarst
22 дек. 2012 г. 16:30:50

@EugeneManuilov Хорошо, извините за длинный ответ. И это после того, как я сократил его до основного!

sanchothefat sanchothefat
24 дек. 2012 г. 04:01:57

Похоже, что первый $permalink = home_url(... перезаписывается $permalink = user_trailingslashit(... и никогда не используется. Или я что-то упускаю? $post_link даже не определен. Возможно, должно было быть $permalink = user_trailingslashit( $permalink, 'single' ); ?

Ian Dunn Ian Dunn
6 февр. 2013 г. 01:07:58

Хорошее замечание, должно быть $permalink, а не $post_link. Спасибо :)

sanchothefat sanchothefat
6 февр. 2013 г. 12:50:58

Я обнаружил баг в вашем плагине WP Permastructure. Оставил issue на Github.

DaveyJake DaveyJake
20 окт. 2021 г. 23:27:26
Показать остальные 1 комментариев
0

Я НАШЕЛ РЕШЕНИЕ!!!

(После бесконечных поисков... Я могу получить ЧПУ для ПРОИЗВОЛЬНОГО ТИПА ЗАПИСЕЙ в таком виде:
example.com/category/sub_category/my-post-name

Вот код (в functions.php или плагине):

//===ШАГ 1 (затронет только эти ПРОИЗВОЛЬНЫЕ ТИПЫ ЗАПИСЕЙ)
$GLOBALS['my_post_typesss__MLSS'] = array('my_product1','....');

//===ШАГ 2  (создаем желаемые ЧПУ)
add_filter('post_type_link', 'my_func88888', 6, 4 );

function my_func88888( $post_link, $post, $sdsd){
    if (!empty($post->post_type) && in_array($post->post_type, $GLOBALS['my_post_typesss']) ) {  
        $SLUGG = $post->post_name;
        $post_cats = get_the_category($id);     
        if (!empty($post_cats[0])){ $target_CAT= $post_cats[0];
            while(!empty($target_CAT->slug)){
                $SLUGG =  $target_CAT->slug .'/'.$SLUGG; 
                if  (!empty($target_CAT->parent)) {$target_CAT = get_term( $target_CAT->parent, 'category');}   else {break;}
            }
            $post_link= get_option('home').'/'. urldecode($SLUGG);
        }
    }
    return  $post_link;
}

// ШАГ 3  (по умолчанию, при обращении к "EXAMPLE.COM/category/postname"
// WP считает, что запрашивается стандартная запись. Поэтому мы добавляем ПРОИЗВОЛЬНЫЙ ТИП ЗАПИСИ
// в этот запрос.
add_action('pre_get_posts', 'my_func4444',  12); 

function my_func4444($q){     
    if ($q->is_main_query() && !is_admin() && $q->is_single){
        $q->set( 'post_type',  array_merge(array('post'), $GLOBALS['my_post_typesss'] )   );
    }
    return $q;
}
26 июл. 2015 г. 22:07:21
2

Решение найдено!

Для создания иерархических постоянных ссылок для произвольного типа записей установите плагин Custom Post Type Permalinks(https://wordpress.org/plugins/custom-post-type-permalinks/).

Обновите регистрацию типа записи. У меня тип записи называется Help Center

function help_centre_post_type(){
    register_post_type('helpcentre', array( 
        'labels'            =>  array(
            'name'          =>      __('Центр помощи'),
            'singular_name' =>      __('Центр помощи'),
            'all_items'     =>      __('Просмотреть записи'),
            'add_new'       =>      __('Новая запись'),
            'add_new_item'  =>      __('Новый центр помощи'),
            'edit_item'     =>      __('Редактировать центр помощи'),
            'view_item'     =>      __('Просмотреть центр помощи'),
            'search_items'  =>      __('Искать в центре помощи'),
            'no_found'      =>      __('Записи центра помощи не найдены'),
            'not_found_in_trash' => __('В корзине нет записей центра помощи')
                                ),
        'public'            =>  true,
        'publicly_queryable'=>  true,
        'show_ui'           =>  true, 
        'query_var'         =>  true,
        'show_in_nav_menus' =>  false,
        'capability_type'   =>  'page',
        'hierarchical'      =>  true,
        'rewrite'=> [
            'slug' => 'help-center',
            "with_front" => false
        ],
        "cptp_permalink_structure" => "/%help_centre_category%/%post_id%-%postname%/",
        'menu_position'     =>  21,
        'supports'          =>  array('title','editor', 'thumbnail'),
        'has_archive'       =>  true
    ));
    flush_rewrite_rules();
}
add_action('init', 'help_centre_post_type');

А вот регистрация таксономии

function themes_taxonomy() {  
    register_taxonomy(  
        'help_centre_category',  
        'helpcentre',        
        array(
            'label' => __( 'Категории' ),
            'rewrite'=> [
                'slug' => 'help-center',
                "with_front" => false
            ],
            "cptp_permalink_structure" => "/%help_centre_category%/",
            'hierarchical'               => true,
            'public'                     => true,
            'show_ui'                    => true,
            'show_admin_column'          => true,
            'show_in_nav_menus'          => true,
            'query_var' => true
        ) 
    );  
}  
add_action( 'init', 'themes_taxonomy');

Эта строка делает ваши постоянные ссылки рабочими

"cptp_permalink_structure" => "/%help_centre_category%/%post_id%-%postname%/",

Вы можете удалить %post_id% и оставить /%help_centre_category%/%postname%/"

Не забудьте сбросить постоянные ссылки в админ-панели.

20 июл. 2017 г. 15:54:59
Комментарии

+1 самое простое решение — просто использовать этот плагин: https://wordpress.org/plugins/custom-post-type-permalinks/ работает идеально

Jules Jules
16 авг. 2017 г. 13:49:02

Да, но это если у вас один пользовательский тип записи, а если у вас несколько пользовательских типов записей в одной теме, то выше приведено решение.

Кроме того, он также изменяет слаг вашей категории на такой же, как у типа записи.

Varsha Dhadge Varsha Dhadge
18 авг. 2017 г. 09:41:01
0
-2

У вас есть несколько ошибок в коде. Я исправил ваш существующий код:

<?php
function jcj_club_post_types() {
  $labels = array(
    'name' => __( 'Джаз-клубы' ),
    'singular_name' => __( 'Джаз-клуб' ),
    'add_new' => __( 'Добавить новый' ),
    'add_new_item' => __( 'Добавить новый джаз-клуб' ),
    'edit' => __( 'Редактировать' ),
    'edit_item' => __( 'Редактировать джаз-клубы' ),
    'new_item' => __( 'Новый джаз-клуб' ),
    'view' => __( 'Просмотреть джаз-клуб' ),
    'view_item' => __( 'Просмотреть джаз-клуб' ),
    'search_items' => __( 'Искать джаз-клубы' ),
    'not_found' => __( 'Джаз-клубы не найдены' ),
    'not_found_in_trash' => __( 'В корзине нет джаз-клубов' ),
    'parent' => __( 'Родительский джаз-клуб' ),
    );
  $args = array(
    'public' => true,
    'show_ui' => true,
    'publicly_queryable' => true,
    'exclude_from_search' => false,
    'menu_position' => 5,
    'query_var' => true,
    'supports' => array( 'title','editor','comments','revisions','trackbacks','author','excerpt','thumbnail','custom-fields' ),
    'rewrite' => array( 'slug' => 'jazz-clubs-in', 'with_front' => true ),
    'has_archive' => true
    );
  register_post_type( 'jcj_club', $args );
  }
add_action( 'init','jcj_club_post_types' );
?>

Замените ваш код на код выше и проверьте, работает ли он. Если у вас остались вопросы, ответьте мне, и я постараюсь помочь.

РЕДАКТИРОВАНО:

Я заметил, что забыл добавить 'has_archive' => true.

30 мая 2012 г. 05:30:51