Вопрос или проблема
Настройка
У меня есть 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()
, но делайте это только один раз в начале или в процессе тестирования, чтобы избежать проблем с производительностью.
Используйте данный подход для достижения максимальной функциональности и удобства для пользователей вашего веб-сайта.