Постоянные ссылки при фильтрации нескольких пользовательских типов записей по одной таксономии

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

Я уже давно работаю с настраиваемыми типами записей и таксономиями, но одна вещь, с которой я никогда не могу разобраться, это переписывание URL-адресов при применении общей таксономии к нескольким CPT.

Например, у меня есть CPT для «Событий» и «Курсов». Каждый имеет отдельные таксономии и также одну общую таксономию.

Отдельные таксономии работают нормально:

  • События с конкретной темой: /events/topic/{term}/
  • Курсы определенного типа: /courses/type/{term}/

Однако у меня есть общая таксономия под названием «Критерии доступности». С определенной ниже настраиваемой таксономией я хочу (и ожидаю) иметь возможность фильтровать каждую CPT по общей таксономии на разных URL:

  • События с конкретными критериями доступности: /events/accessibility/{term}/
  • Курсы с конкретными критериями доступности: /courses/accessibility/{term}/

Но всякий раз, когда я пытаюсь использовать /events/accessibility/{term}/, он переписывается как /accessibility/{term}/. Удивительно (для меня), что контекст на самом деле сохраняется правильно, например, если я активирую таксономию из архива событий, тогда показываются только CPT событий, так что пользовательский опыт все равно работает нормально. Тем не менее, мне это не очень нравится, так как я считаю, что это должно работать иначе (а также потенциально лучше с точки зрения SEO и т. д.).

Я определил настраиваемые таксономии перед определением CPT, так как читал, что это влияет на возможность CPT использовать переписывание таксономии.

Буду признателен за любую помощь.

$labels = array(
  "name" => __('Критерии доступности', ''),
  "singular_name" => __('Критерий доступности', ''),
  "add_new_item" => __('Добавить критерий доступности', ''),
  "new_item_name" => __('Добавить критерий доступности', ''),
  "edit_item" => __('Редактировать критерий доступности', ''),
  "view_item" => __('Просмотреть критерий доступности', ''),
  "update_item" => __('Обновить критерий доступности', ''),
  "parent_item" => __('Родительский критерий', '')
);
$args = array(
  "label" => __('Критерии доступности', ''),
  "labels" => $labels,
  "public" => true,
  "hierarchical" => true,
  "label" => "Критерии доступности",
  "show_ui" => true,
  "show_in_menu" => true,
  "show_in_nav_menus" => false,
  "capabilities" => array(
    'manage_terms' => 'manage_accessibility_criteria',
    'edit_terms'   => 'edit_accessibility_criteria',
    'delete_terms' => 'delete_accessibility_criteria',
    'assign_terms' => 'assign_accessibility_criteria'
  ),
  "query_var" => 'accessibility_criteria',
  "rewrite" => array('slug' => 'accessibility', 'with_front' => true),
  "show_admin_column" => true,
  "show_in_rest" => false,
  "rest_base" => "",
  "show_in_quick_edit" => true,
);
register_taxonomy("accessibility_criteria", array("event", "course"), $args);

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

Сначала: удалите аргумент «rewrite» из ваших аргументов register_taxonomy (не уверен, что вам обязательно нужно это сделать, но у меня это работает на сайте)

Во-вторых: добавьте правило переписывания так:

add_action( 'init', 'wpse13483_init' );
function wpse292188_init(){   
    add_rewrite_rule('(events|courses)/accessibility/([^/]+)(/page/?([0-9]{1,}))?/?$','index.php?post_type=$matches[1]&taxonomy=accessibility&term=$matches[2]&paged=$matches[3]','top');
}

Не забудьте сохранить постоянные ссылки после загрузки!

Счастливого кодирования!

Вам нужно добавить эти постоянные ссылки самостоятельно. Я не вижу никакого кода в WordPress, который создает постоянные ссылки в формате $post_type/$taxonomy/$term. Я также не вижу таких правил в своем массиве правил переписывания после создания настраиваемой таксономии, назначенной только одному настраиваемому типу записи. Поведение вашего приложения может быть вызвано каким-то плагином. Ниже вы найдете код, который добавит настраиваемые постоянные ссылки для структуры $post_type/$taxonomy/$term и загрузит настраиваемый шаблон, когда такая постоянная ссылка будет посещена.

<?php
/**
 * Регистрация типа записи события
 *
 * Метод используется хуком init
 */
function wpse_292188_register_event_post_type() {

    $labels = array(
        'name' => __( 'События' ),
        'singular_name' => __( 'Событие' ),
        'add_new' => __( 'Добавить новое' ),
        'add_new_item' => __( 'Добавить новое' ),
        'edit_item' => __( 'Редактировать' ),
        'new_item' => __( 'Новое' ),
        'view_item' => __( 'Просмотреть' ),
        'search_items' => __( 'Поиск' ),
        'not_found' => __( 'Не найдено' ),
        'not_found_in_trash' => __( 'События не найдены в корзине' ),
        'parent_item_colon' => __( 'Родитель' ),
        'menu_name' => __( 'События' ),

    );

    $args = array(
        'labels' => $labels,
        'hierarchical' => false,
        'supports' => array( 'title', 'page-attributes' ),
        'taxonomies' => array(),
        'public' => true,
        'show_ui' => true,
        'show_in_menu' => true,
        'show_in_nav_menus' => false,
        'publicly_queryable' => true,
        'exclude_from_search' => false,
        'has_archive' => true,
        'query_var' => true,
        'can_export' => true,
        'rewrite' => array('slug' => 'event'),
        'capability_type' => 'post',
    );

    register_post_type( 'event', $args );
}

add_action( 'init', 'wpse_292188_register_event_post_type' );

/**
 * Регистрация типа записи курса
 *
 * Метод используется хуком init
 */
function wpse_292188_register_course_post_type() {

    $labels = array(
        'name' => __( 'Курсы' ),
        'singular_name' => __( 'Курс' ),
        'add_new' => __( 'Добавить новый' ),
        'add_new_item' => __( 'Добавить новый' ),
        'edit_item' => __( 'Редактировать' ),
        'new_item' => __( 'Новое' ),
        'view_item' => __( 'Просмотреть' ),
        'search_items' => __( 'Поиск' ),
        'not_found' => __( 'Не найдено' ),
        'not_found_in_trash' => __( 'Курсы не найдены в корзине' ),
        'parent_item_colon' => __( 'Родитель' ),
        'menu_name' => __( 'Курсы' ),

    );

    $args = array(
        'labels' => $labels,
        'hierarchical' => false,
        'supports' => array( 'title', 'page-attributes' ),
        'taxonomies' => array(),
        'public' => true,
        'show_ui' => true,
        'show_in_menu' => true,
        'show_in_nav_menus' => false,
        'publicly_queryable' => true,
        'exclude_from_search' => false,
        'has_archive' => true,
        'query_var' => true,
        'can_export' => true,
        'rewrite' => array('slug' => 'course'),
        'capability_type' => 'post',
    );

    register_post_type( 'course', $args );
}

add_action( 'init', 'wpse_292188_register_course_post_type' );

/**
 * Регистрация таксономии accessibility_criteria
 *
 * Метод используется хуком init
 */
function wpse_292188_register_accessibility_criteria_taxonomy() {

    $labels = array(
        'name'              => __( 'Критерии доступности', 'textdomain' ),
        'singular_name'     => __( 'Критерий доступности', 'textdomain' ),
        'search_items'      => __( 'Поиск критериев доступности', 'textdomain' ),
        'all_items'         => __( 'Все критерии доступности', 'textdomain' ),
        'parent_item'       => __( 'Родительский критерий доступности', 'textdomain' ),
        'parent_item_colon' => __( 'Родительский критерий доступности:', 'textdomain' ),
        'edit_item'         => __( 'Редактировать критерий доступности', 'textdomain' ),
        'update_item'       => __( 'Обновить критерий доступности', 'textdomain' ),
        'add_new_item'      => __( 'Добавить новый критерий доступности', 'textdomain' ),
        'new_item_name'     => __( 'Новое имя критерия доступности', 'textdomain' ),
        'menu_name'         => __( 'Критерии доступности', 'textdomain' ),
    );

    $args = array(
        'hierarchical'      => true,
        'labels'            => $labels,
        'show_ui'           => true,
        'show_admin_column' => true,
        'query_var'         => true,
        'rewrite'           => array( 'slug' => 'accessibility' ),
    );

    register_taxonomy( 'accessibility_criteria', array( 'event', 'course' ), $args );
}

add_action( 'init', 'wpse_292188_register_accessibility_criteria_taxonomy' );

/**
 * Добавление правил переписывания для общей таксономии
 *
 * @return void
 */
function wpse_292188_add_taxonomy_and_post_type_rewrite_rule() {

    /**
     * Это правило переписывания будет соответствовать следующим ссылкам
     *
     * /event/accessibility/criteria-1
     * /event/accessibility/criteria-1/page/2
     *
     * /course/accessibility/criteria-1
     * /course/accessibility/criteria-1/page/2
     *
     * и «перенаправит» их на index.php с такими аргументами
     *
     * index.php?post_type=event&accessibility_criteria=criteria-1
     * index.php?post_type=event&accessibility_criteria=criteria-1&paged=2
     *
     * index.php?post_type=course&accessibility_criteria=criteria-1
     * index.php?post_type=course&accessibility_criteria=criteria-1&paged=2
     */
    add_rewrite_rule( 'event/accessibility/([^/]+)/?', 'index.php?post_type=event&accessibility_criteria=$matches[1]', 'top' );
    add_rewrite_rule( 'event/accessibility/([^/]+)/page/?([0-9]{1,})/?', 'index.php?pots_type=eventaccessibility_criteria=$matches[1]&paged=$matches[2]', 'top' );

    add_rewrite_rule( 'course/accessibility/([^/]+)/?', 'index.php?post_type=course&accessibility_criteria=$matches[1]', 'top' );
    add_rewrite_rule( 'course/accessibility/([^/]+)/page/?([0-9]{1,})/?', 'index.php?pots_type=courseaccessibility_criteria=$matches[1]&paged=$matches[2]', 'top' );

}

add_action( 'init', 'wpse_292188_add_taxonomy_and_post_type_rewrite_rule' );

/**
 * Регистрация хуков активации. Работает только в файле плагина.
 */
register_activation_hook( __FILE__ , 'wpse_292188_activate' );
register_deactivation_hook( __FILE__ , 'wpse_292188_deactivate' );

/**
 * Функция активации
 */
function wpse_292188_activate() {

    wpse_292188_add_taxonomy_and_post_type_rewrite_rule();
    flush_rewrite_rules();
}
/**
 * Функция деактивации
 */
function wpse_292188_deactivate() {

    flush_rewrite_rules();
}

/**
 * Загрузка подходящего шаблона для правила переписывания таксономии и типа записи
 *
 * @return string
 *
 * @throws \Exception Когда шаблон не существует.
 */
function wpse_292188_load_proper_template_for_taxonomy_and_post_type_rewrite_rule( $template ) {

    $post_type              = get_query_var('post_type');
    $accessibility_criteria = get_query_var('accessibility_criteria');

    /**
     * Проверяем, есть ли у текущей страницы тип записи и пользовательская
     * переменная запроса accessibility_criteria. Если да, загружаем наш шаблон.
     */
    if( $post_type && !empty( $post_type ) && $accessibility_criteria && !empty( $accessibility_criteria ) ) {

        /**
         * Найдите наш настраиваемый шаблон. Вы можете использовать переменные $post_type и/или
         * $accessibility_criteria для создания настраиваемого шаблона.
         */
        $template = locate_template( array( 'taxonomy.php' ) );
    }

    if( $template == '' ) {
        throw new \Exception('Шаблон не найден');
    }

    return $template;
}

add_filter( 'template_include', 'wpse_292188_load_proper_template_for_taxonomy_and_post_type_rewrite_rule' );

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

Я явно опоздал на вечеринку, но на всякий случай, если кто-то еще ищет решение, мне удалось сделать что-то похожее, используя некоторые идеи из ответа kierzniak выше.

У меня есть 3 CPT (новости, события, загрузки), которые используют одну и ту же группу таксономий (стратегия), но я не мог разобраться с правилами переписывания, чтобы всё работало.

В конце концов, вот что я установил в своей функции init, которая работает нормально:

add_rewrite_rule( '(news|events|downloads)/strategy/([^/]+)/?', 'index.php?post_type=$matches[1]&strategy=$matches[2]', 'top' );
add_rewrite_rule( '(news|events|downloads)/strategy/([^/]+)/page/?([0-9]{1,})/?', 'index.php?post_type=$matches[1]&strategy=$matches[2]&paged=$matches[3]', 'top' );
add_rewrite_rule( '(news|events|downloads)/strategy/([^/]+)/feed/(feed|rdf|rss|rss2|atom)/?', 'index.php?post_type=$matches[1]&strategy=$matches[2]&feed=$matches[3]', 'top' );
add_rewrite_rule( '(news|events|downloads)/strategy/([^/]+)/(feed|rdf|rss|rss2|atom)/?', 'index.php?post_type=$matches[1]&strategy=$matches[2]&feed=$matches[3]', 'top' );

.

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

Вопрос фильтрации нескольких пользовательских типов записей (Custom Post Types, CPT) по единой таксономии (taxonomy) в WordPress часто вызывает сложности у разработчиков. В данном случае мы рассматриваем ситуацию, в которой существует два CPT: «События» (Events) и «Курсы» (Courses), использующие общую таксономию — «Критерии доступности» (Accessibility Criteria). Попробуем разобраться, как настроить правильные постоянные ссылки (permalinks) для фильтрации по этой общей таксономии для каждого CPT.

Проблема

Как указано в запросе, при попытке создать URL для фильтрации событий по критериям доступности (/events/accessibility/{term}/), система автоматически переписывает его в более общее представление (/accessibility/{term}/). Хотя фильтрация по таксономии работает корректно (в пользовательском интерфейсе отображаются только события или курсы), на уровне структуры URL эта ситуация не удовлетворяет желание иметь специфические URL для каждого CPT.

Решение

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

  1. Удалите аргумент "rewrite" из определения вашей таксономии. Это необходимо, поскольку WordPress по умолчанию не создает пути в формате post_type/taxonomy/term.

  2. Добавьте индивидуальные правила переопределения в файл functions.php вашей темы. Следующий код добавит правила, которые обеспечат нужный вам формат URL, а также учтет, как передать параметры в запрос:

add_action('init', 'custom_rewrite_rules');
function custom_rewrite_rules() {
    add_rewrite_rule('events/accessibility/([^/]+)/?', 'index.php?post_type=event&accessibility_criteria=$matches[1]', 'top');
    add_rewrite_rule('events/accessibility/([^/]+)/page/?([0-9]{1,})/?', 'index.php?post_type=event&accessibility_criteria=$matches[1]&paged=$matches[2]', 'top');

    add_rewrite_rule('courses/accessibility/([^/]+)/?', 'index.php?post_type=course&accessibility_criteria=$matches[1]', 'top');
    add_rewrite_rule('courses/accessibility/([^/]+)/page/?([0-9]{1,})/?', 'index.php?post_type=course&accessibility_criteria=$matches[1]&paged=$matches[2]', 'top');
}
  1. Не забудьте сохранить постоянные ссылки после того, как вы внесли изменения. Это приведет к обновлению правил переопределения, что является необходимым шагом для правильной работы новых URL.

С учетом контекста SEO

При создании структурированных URL важно учитывать и SEO-оптимизацию. Указание четких и логичных URL-адресов помогает поисковым системам лучше индексировать содержание вашего сайта. Для данной ситуации URL /events/accessibility/{term}/ и /courses/accessibility/{term}/ способствуют ясному пониманию контента обеих категорий и позволяют избежать конфликтов между ними.

Заключение

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

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

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