Пользовательская таксономия на постоянной ссылке

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

У меня длительная проблема, и я надеюсь на вашу помощь.
У меня есть пользовательская таксономия “город” (она не иерархическая, как теги).
Я просто хотел бы, чтобы мои URL выглядели так:

/%city%/%category%/%postname%/

Так что вот, что я хочу добиться.

  • http://example.com/city/moscow – Показать все записи в таксономии город-Москва.
  • http://example.com/category/shopping – Показать все записи в этой категории и во всех городах.
  • http://example.com/category/shopping/supermarket – Показать все записи в этой категории и во всех городах.
  • http://example.com/moscow/shopping/ – Показать все записи в этой категории в Москве.
  • http://example.com/moscow/shopping/supermarket/ – Показать все записи в этой дочерней категории в Москве.
  • http://example.com/moscow/shopping/supermarket/postname – Показать запись.

Я сделал следующее:

  1. Сначала я создал пользовательскую таксономию – город.
  2. Я добавил код в function.php
function add_custom_taxonomies_city() {
    register_taxonomy('city', 'post', array(
        'hierarchical' => false,
        'labels' => array(
            'name' => _x( 'Город', 'таксономия общее имя' ),
            'search_items' =>  __( 'Искать города' ),
            'all_items' => __( 'Все города' ),
            'parent_item' => __( 'Родительские категории' ),
            'parent_item_colon' => __( 'Родительские категории:' ),
            'edit_item' => __( 'Редактировать город' ), 
            'update_item' => __( 'Обновить город' ),
            'add_new_item' => __( 'Добавить город' ),
            'new_item_name' => __( 'Новый город' ),
            'menu_name' => __( 'города' ),
            );    

        ),
    'rewrite' => array(
        'slug' => 'city',
        'with_front' => false,
        'hierarchical' => false
        ),
    ));
}
add_action( 'init', 'add_custom_taxonomies_city', 0 ); 

add_filter('post_link', 'town_permalink', 10, 3);
add_filter('post_type_link', 'town_permalink', 10, 3);

function town_permalink($permalink, $post_id, $leavename) {
    if (strpos($permalink, '%city%') === FALSE) return $permalink;

// Получить запись
    $post = get_post($post_id);
    if (!$post) return $permalink;

// Получить термины таксономии
    $terms = wp_get_object_terms($post->ID, 'city');  
    if (!is_wp_error($terms) && !empty($terms) && is_object($terms[0])) $taxonomy_slug = $terms[0]->slug;
    else $taxonomy_slug = 'not-city';

    return str_replace('%city%', $taxonomy_slug, $permalink);
}

Результат:

  • http://example.com/city/moscow – Работает
  • http://example.com/category/shopping – Работает
  • http://example.com/category/shopping/supermarket/ – Работает
  • http://example.com/moscow/shopping/ – Работает
  • http://example.com/moscow/shopping/supermarket/ – Не работает!!!!!
  • http://example.com/moscow/shopping/supermarket/postname – Не работает!!!!!

Этот пост имеет следующую ссылку: http: //mysite.ru/ moscow/shopping/postname

Но мне нужно, чтобы ссылки содержали дочернюю категорию.

  1. Я попробовал решить задачу с другой опцией: я добавил следующий код в function.php
function addRoutes() {
    add_rewrite_tag('%city%', '(.+?)');
    add_rewrite_rule('(.+?)/(.+?)/([^/]+)(/[0-9]+)?/?$', 'index.php?city=$matches[1]&category_name=$matches[2]&name=$matches[3]&page=$matches[4]', 'top');
  add_rewrite_rule('(.?.+?)(/[0-9]+)?/?$', 'index.php?pagename=$matches[1]&page=$matches[2]', 'top');
    flush_rewrite_rules();
}
add_action('init', 'addRoutes');

В результате

http://example.com/city/moscow – Ошибка 404.
http://example.com/category/shopping – Ошибка 404.
http://example.com/category/shopping/supermarket/ – Ошибка 404.
http://example.com/moscow/shopping/supermarket/postname – Ошибка 400

Кажется, система не понимает %city%
Что не так?
Жду вашей помощи
Может кто-нибудь помочь мне?
Большое спасибо!


Я решил изменить структуру URL на:

  • example.com/city/moscow/category/shopping/ – Показать все записи в этой категории в Москве.
  • example.com/city/moscow/category/shopping/supermarket/ – Показать все записи в этой дочерней категории в Москве.
  • example.com/city/moscow/category/shopping/supermarket/postname – Показать запись.

Код:

//Правила переписывания
function eg_add_query_vars( $query_vars ) {
    $new_vars = array( 'town' );

    return array_merge( $new_vars, $query_vars );
}
add_filter( 'query_vars', 'eg_add_query_vars' );

function eg_add_rewrite_rules() {
    global $wp_rewrite;

    $new_rules = array(
        'city/(.+?)/category/(.+?)/?$' => 'index.php?city=' . $wp_rewrite->preg_index(1) . '&category_name=" . $wp_rewrite->preg_index(2),
"city/(.+?)/category/(.+?)/(.+?)/?$' => 'index.php?city=' . $wp_rewrite->preg_index(1) . '&category_name=" . $wp_rewrite->preg_index(2) . "&category_name=". $wp_rewrite->preg_index(3),

//"city/(.+?)/category/(.+?)/(.+?)/(.+?)/?$' => 'index.php?city=' . $wp_rewrite->preg_index(1) . '&category_name=" . $wp_rewrite->preg_index(2) . "&category_name=". $wp_rewrite->preg_index(3). "&page=". $wp_rewrite->preg_index(4),// Это моё усилие написать правило для постов (не работает)   
        );
    $wp_rewrite->rules = $new_rules + $wp_rewrite->rules;
}
add_action( 'generate_rewrite_rules', 'eg_add_rewrite_rules' );


//создание постоянной ссылки:
function city_permalink($permalink, $post_id, $leavename) {
    if (strpos($permalink, '%city%') === FALSE) return $permalink;

        // Получить пост
        $post = get_post($post_id);
        if (!$post) return $permalink;

        // Получить термины таксономии
        $terms = wp_get_object_terms($post->ID, 'town');  
        if (!is_wp_error($terms) && !empty($terms) && is_object($terms[0])) $taxonomy_slug = $terms[0]->slug;
        else $taxonomy_slug = 'not-city';

    return str_replace('%town%', $taxonomy_slug, $permalink);}

    function wp_town_query( $query ) {
    if( isset( $query->query_vars['city'] ) ):
        if( $city = get_term_by( 'id', $query->query_vars['city'], 'city' ) )
            $query->query_vars['town'] = $city->slug;
    endif;
}
add_action( 'parse_query', 'wp_city_query' );

Мои настройки на странице администрирования Постоянные ссылки:
city/%city%/category/%category%/%postname%/

В результате я имею:
example.com/city/moscow/category/shopping/ – работает
example.com/city/moscow/category/shopping/supermarket/ – работает
но я все еще не могу понять, как написать правило для постов:
example.com/city/moscow/category/shopping/supermarket/postname – не работает.
Пагинация тоже не работает.

Я буду рад любым советам!

Это работает:


'city/(.+?)/category/(.+?)/(.+?)/([^/]+)/?$' => 'index.php?city=' . $wp_rewrite->preg_index(1) . '&category_name=" . $wp_rewrite->preg_index(2). "&category_name=" . $wp_rewrite->preg_index(3). "&name=" . $wp_rewrite->preg_index(4), 
"city/(.+?)/category/(.+?)/page/?([0-9]{1,})/?$' => 'index.php?city=' . $wp_rewrite->preg_index(1) . '&category_name=" . $wp_rewrite->preg_index(2). "&paged=' . $wp_rewrite->preg_index(3),
'city/(.+?)/category/(.+?)/?$' => 'index.php?city=' . $wp_rewrite->preg_index(1) . '&category_name=" . $wp_rewrite->preg_index(2),  

Хорошо, я получу отрицательные баллы за это, но это должно решить вашу проблему, пожалуйста, не сердитесь на меня.
Прежде чем кто-то даст мне минус за это, я должен сказать, что я не имею ничего общего с разработчиками этого плагина:

Для пользовательских таксономий и пользовательских типов записей я часто использую плагин под названием “Types“. Вы можете найти его в списке установленных плагинов в меню WordPress, и он должен решить вашу проблему без кодирования.

Ответ или решение

Настройка пользовательской таксономии и ЧПУ в WordPress

У вас есть задача настроить пользовательскую таксономию "город" (city) в WordPress и выстроить для неё удобные и понятные URL-адреса. Ниже приведены шаги, которые помогут вам правильно реализовать вашу конфигурацию.

Шаг 1: Регистрация пользовательской таксономии

Вы уже создали пользовательскую таксономию "город" с помощью следующего кода в functions.php:

function add_custom_taxonomies_city() {
    register_taxonomy('city', 'post', array(
        'hierarchical' => false,
        'labels' => array(
            'name' => _x('City', 'taxonomy general name'),
            'search_items' => __('Search cities'),
            'all_items' => __('All cities'),
            'edit_item' => __('Edit city'), 
            'update_item' => __('Update city'),
            'add_new_item' => __('Add city'),
            'new_item_name' => __('New city'),
            'menu_name' => __('cities'),
        ),    
        'rewrite' => array(
            'slug' => 'city',
            'with_front' => false,
            'hierarchical' => false
        ),
    ));
}
add_action('init', 'add_custom_taxonomies_city', 0);

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

Шаг 2: Настройка структуры URL

Для достижения желаемой структуры URL /%city%/%category%/%postname%/, вы должны изменить правила переписывания. Ваш изначальный код для создания правил выглядит многообещающе, но нуждается в доработке.

Корректировка правил переписывания
  1. Замените ваш код для добавления правил:
function addRoutes() {
    add_rewrite_tag('%city%', '(.+?)');
    add_rewrite_rule('^city/([^/]+)/category/([^/]+)/?$', 'index.php?city=$matches[1]&category_name=$matches[2]', 'top');
    add_rewrite_rule('^city/([^/]+)/category/([^/]+)/([^/]+)/?$', 'index.php?city=$matches[1]&category_name=$matches[2]&name=$matches[3]', 'top');
    flush_rewrite_rules(); // Важно: вызовите очищение правил переписывания
}
add_action('init', 'addRoutes');
  1. Обратите внимание на flush_rewrite_rules(). Этот вызов следует использовать с осторожностью и не в каждом init, а только при необходимости (например, после изменения правил). Лучше вызвать его в админке, например, через кнопку.

Шаг 3: Формирование ссылок для постов

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

add_filter('post_link', 'town_permalink', 10, 3);
add_filter('post_type_link', 'town_permalink', 10, 3);

function town_permalink($permalink, $post_id, $leavename) {
    if (strpos($permalink, '%city%') === false) return $permalink;

    $post = get_post($post_id);
    if (!$post) return $permalink;

    $terms = wp_get_object_terms($post->ID, 'city');  
    if (!is_wp_error($terms) && !empty($terms) && is_object($terms[0])) {
        $taxonomy_slug = $terms[0]->slug;
    } else {
        $taxonomy_slug = 'not-city';
    }

    return str_replace('%city%', $taxonomy_slug, $permalink);
}

Убедитесь, что в ваших настройках постоянных ссылок выбран формат /%city%/%category%/%postname%/.

Шаг 4: Обработка запроса

Вам нужно обработать запрос, чтобы WordPress корректно распознавал ваши новые параметры URL:

add_action('pre_get_posts', 'wp_city_query');
function wp_city_query($query) {
    if ($query->is_main_query() && !is_admin() && isset($query->query_vars['city'])) {
        $city = $query->query_vars['city'];
        $query->set('tax_query', array(
            array(
                'taxonomy' => 'city',
                'field' => 'slug',
                'terms' => $city,
            ),
        ));
    }
}

Шаг 5: Проверка и отладка

После всех изменений проверьте, что у вас нет ошибок 404, и убедитесь, что система обрабатывает запросы как ожидается. Возможно, потребуется очищение кеша, если он установлен на сайте.

Заключение

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

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

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