Пагинация конечной точки пользовательской таксономии с использованием paginate_links()

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

Настройка

У меня есть 2 таксономии и 1 тип записи:

  • Тип записи: products
  • Иерархическая таксономия: product_cat
  • Неиерархическая таксономия: product_type

Таксономия product-category имеет определённую конечную точку:

add_endpoint( 'types', EP_PRODUCT_CAT );

Теперь я пытаюсь создать довольно длинный URL, который комбинирует обе таксономии:

https://www.example.com/products/parent-product-cat/child-product-cat/types/top-product-type/

Это работает, переменная запроса types установлена, переменная product_cat также задана – радужные и жевательные резинки.

Проблема

Пагинация. Я использую paginate_links(), который полностью удаляет мою переменную запроса types и передаёт её значение переменной запроса product_cat, что приводит к ошибке 404. Следы начинаются с параметра add_args функции paginate_links(). Я могу передать обе product_cat и types, и пагинация работает:

global $wp_query;
$term_cat  = get_term_by( 'slug', get_query_var( 'term' ), get_query_var( 'taxonomy' ) );
$term_type = get_term_by( 'slug', get_query_var( 'types' ), 'product_type' );

echo paginate_links( array(
        'base'          => '%_%',
        'format'        => '?paged=%#%',
        'current'       => max( 1, get_query_var( 'paged' ) ),
        'total'         => $wp_query->max_num_pages,
        'end_size'      => 0,
        'mid_size'      => 2,
        'prev_next'     => false,
        'add_args'      => array(
            'product_cat'   => $term_cat->slug,
            'types'         => $term_type->slug,
        ),
) );

Так что переменные запроса теперь есть, но постоянные ссылки стали некрасивыми, так как paginate_links() просто добавляет их как параметры $_GET:

https://www.example.com/products/parent-product-cat/child-product-cat/types/top-product-type/page/2/?product_cat=abc&types=123

Так как структура постоянных ссылок всё ещё intact во время пагинации, я не уверен, помогут ли правила переписывания на данном этапе – но я попробовал, и это не кажется эффективным:

/**
 * Конечные точки и переписывания
 *
 * @return void
 */
function theme_endpoints_rewrites() {
    add_rewrite_rule( '^products/([^/]+)/types/([^/]+)/page/([0-9]+)/?', 'index.php?post_type=products&product_cat=$matches[1]&types=$matches[3]&paged=$matches[4]', 'top' );
    add_rewrite_endpoint( 'types', EP_PRODUCT_CAT );
    flush_rewrite_rules(true);
}
add_action( 'init', 'theme_endpoints_rewrites' );

Я также попробовал изменить URL страниц пагинации на home_url() и попытался переписать его с учётом переданных аргументов, но тоже безуспешно. Если я оставляю структуру постоянных ссылок по умолчанию ( plain ), страницы загружаются как и ожидалось. Похоже, это происходит всякий раз, когда WordPress переписывает переменную запроса paged.


Ниже почти работает. Это показывает, что product_cat имеет правильное/ожидаемое значение, но он объединяет как types, так и paged переменные запроса в одно значение, так что моя переменная запроса содержит [types] => cotton/page/2 и игнорирует переменную запроса paged.

function test_rewrites( $wp_rewrite ) {

    $wp_rewrite->rules['products/(.+?)/types/(.+?)/page/?([0-9]{1,})/?$'] = 'index.php?product_cat=$matches[1]&types=$matches[2]&paged=$matches[3]';
    unset( $wp_rewrite->rules['products/(.+?)/page/?([0-9]{1,})/?$'] );
    unset( $wp_rewrite->extra_rules_top['products/(.+?)/page/?([0-9]{1,})/?$'] );

}
add_action( 'generate_rewrite_rules', 'test_rewrites' );

Кто-нибудь знает, как я могу добавить пагинацию к конечной точке, сохраняя желаемые URL?

Вам нужно зарегистрировать тип записи и две таксономии для него:

/**
 * Регистрация пользовательского типа записи продукта и таксономий
 */
function wp_qhywe2x_register_product_custom_post_type() {

    register_post_type( 'product', array(
        'label'       => __( 'Продукт', 'text-domain' ),
        'labels'      => array(
            'name'           => __( 'Продукты', 'text-domain' ),
            'singular_name'  => __( 'Продукт', 'text-domain' ),
            'menu_name'      => __( 'Продукты', 'text-domain' ),
            'name_admin_bar' => __( 'Продукты', 'text-domain' ),
            'new_item'       => __( 'Новый продукт', 'text-domain' ),
            'edit_item'      => __( 'Редактировать продукт', 'text-domain' ),
            'view_item'      => __( 'Просмотр продукта', 'text-domain' ),
            'all_items'      => __( 'Все продукты', 'text-domain' ),
        ),
        'public'      => true,
        'has_archive' => true,
        'rewrite'     => array( 'slug' => 'product' ),
        'supports'    => array( 'title', 'editor', 'thumbnail' ),
        'menu_icon'   => 'dashicons-cart',
    ) );

    register_taxonomy( 'product_category', array( 'product' ), array(
        'hierarchical'      => true,
        'labels'            => array(
            'name'          => __( 'Категории продуктов', 'text-domain' ),
            'singular_name' => __( 'Категория продукта', 'text-domain' ),
        ),
        'show_ui'           => true,
        'show_admin_column' => true,
        'query_var'         => true,
        'rewrite'           => array( 'slug' => 'product-category' ),
    ) );

    register_taxonomy( 'product_tag', array( 'product' ), array(
        'hierarchical'      => false,
        'labels'            => array(
            'name'          => __( 'Теги продуктов', 'text-domain' ),
            'singular_name' => __( 'Тег продукта', 'text-domain' ),
        ),
        'show_ui'           => true,
        'show_admin_column' => true,
        'query_var'         => true,
        'rewrite'           => array( 'slug' => 'product-tag' ),
    ) );
}

add_action( 'init', 'wp_qhywe2x_register_product_custom_post_type' );

В моем примере тип записи product и для него таксономии product_category и product_tag.

Необходимые настройки уже сделаны с параметром плоского переписывания в аргументах register_taxonomy(), никаких дополнительных настроек не требуется с другой функцией.

Затем вам нужно правило переписывания, чтобы обрабатывать категорию и тег одновременно:

/**
 * Правила переписывания категорий продукта и тегов
 *
 * @param $wp_rewrite
 */
function wp_qhywe2x_product_category_and_tag_rewrite_rules( $wp_rewrite ) {
    $category_rewrite_rules = array();

    $product_obj      = get_post_type_object( 'product' );
    $product_category = get_taxonomy( 'product_category' );
    $product_tag      = get_taxonomy( 'product_tag' );

    /** правило переписывания категории продукта и тега */
    $category_rewrite_rules[ $product_obj->rewrite['slug'] . "https://wordpress.stackexchange.com/" . $product_category->rewrite['slug'] . '/([^/]*)/' . $product_tag->rewrite['slug'] . '/([^/]*)$' ] = 'index.php?post_type=" . $product_obj->name . "&' . $product_category->query_var . '=$matches[1]' . '&' . $product_tag->query_var . '=$matches[2]';

    /** правило переписывания пагинации - page/1 на ?paged=1 */
    $category_rewrite_rules[ $product_obj->rewrite['slug'] . "https://wordpress.stackexchange.com/" . $product_category->rewrite['slug'] . '/([^/]*)/' . $product_tag->rewrite['slug'] . '/([^/]*)/page/([^/]*)$' ] = 'index.php?post_type=" . $product_obj->name . "&' . $product_category->query_var . '=$matches[1]' . '&' . $product_tag->query_var . '=$matches[2]&paged=$matches[3]';

    /** добавление в правила переписывания wp */
    $wp_rewrite->rules = $category_rewrite_rules + $wp_rewrite->rules;
}

add_action( 'generate_rewrite_rules', 'wp_qhywe2x_product_category_and_tag_rewrite_rules' );

Эта функция использует $product_category->rewrite['slug'] и $product_tag->rewrite['slug'], которые были установлены в функции register_taxonomy().

Используйте следующую структуру URL для архива:

http://localhost/product/product-category/plugin/product-tag/awesome/

Это отобразит все продукты, которые имеют категорию “plugin” и тег “awesome“.

Если вы используете функцию the_posts_pagination() или paginate_links() на странице архива, она будет отображать пагинацию идеально, дополнительных настроек не требуется.

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

Пагинация для пользовательских таксономий с использованием paginate_links()

Введение

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

Описание проблемы

Вы настраиваете оболочки продуктов с двумя таксономиями: иерархической (product_cat) и неиерархической (product_type). У вас уже определен конечный путь для таксономии product_cat, и вы пытаетесь собрать URL, который бы выглядел как:

https://www.example.com/products/parent-product-cat/child-product-cat/types/top-product-type/

Однако, при использовании функции paginate_links(), вы сталкиваетесь с проблемой: types теряется, и вместо этого его значение присваивается product_cat, что приводит к ошибке 404. Основным источником проблемы является то, что параметры запроса неправильно передаются в пагинацию.

Решение

1. Настройка параметров

Чтобы обеспечить корректную работу пагинации и избежать проблем с URL, используя paginate_links(), вам необходимо правильно настроить вызов этой функции. Важным моментом является передача правильных параметров в add_args. Вот как это можно сделать:

global $wp_query;
$term_cat  = get_term_by( 'slug', get_query_var( 'term' ), get_query_var( 'taxonomy' ) );
$term_type = get_term_by( 'slug', get_query_var( 'types' ), 'product_type' );

echo paginate_links( array(
    'base'      => '%_%',
    'format'    => 'page/%#%',
    'current'   => max( 1, get_query_var( 'paged' ) ),
    'total'     => $wp_query->max_num_pages,
    'end_size'  => 0,
    'mid_size'  => 2,
    'prev_next' => false,
    'add_args'  => array(
        'product_cat' => $term_cat->slug,
        'types'       => $term_type->slug,
    ),
) );

Этот код необходимо дополнить настройкой правил перезаписи.

2. Перезапись правил

Чтобы исправить проблемы с URL и обеспечить корректную работу с пагинацией, вы должны задать пользовательские правила перезаписи. Используйте следующий код:

function theme_endpoints_rewrites() {
    add_rewrite_rule( '^products/([^/]+)/types/([^/]+)/page/([0-9]+)/?', 'index.php?post_type=products&product_cat=$matches[1]&types=$matches[2]&paged=$matches[3]', 'top' );
}

add_action( 'init', 'theme_endpoints_rewrites' );

Это правило будет обрабатывать запрашиваемые URL-адреса в соответствии с вашей логикой.

3. Регистрация таксономий и типов записи

Убедитесь, что ваши таксономии и типы записи зарегистрированы правильно. Вот пример кода:

function wp_register_product_post_type() {
    register_post_type( 'products', array(
        'label'       => __( 'Products' ),
        'public'      => true,
        'has_archive' => true,
        'rewrite'     => array( 'slug' => 'products' ),
    ) );

    register_taxonomy( 'product_cat', 'products', array(
        'hierarchical' => true,
        'rewrite'      => array( 'slug' => 'product-category' ),
    ) );

    register_taxonomy( 'product_type', 'products', array(
        'hierarchical' => false,
        'rewrite'      => array( 'slug' => 'types' ),
    ) );
}

add_action( 'init', 'wp_register_product_post_type' );

Заключение

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

Не забывайте очищать правила перезаписи при изменениях с помощью flush_rewrite_rules(), но делайте это только один раз в начале или в процессе тестирования, чтобы избежать проблем с производительностью.

Используйте данный подход для достижения максимальной функциональности и удобства для пользователей вашего веб-сайта.

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

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