Лучше всего посмотреть, что происходит под капотом. С помощью плагина Query Monitor можно увидеть результирующий запрос и проанализировать его. Я специально создал несколько категорий и постов, и для отладки одному посту назначил 3 категории, одна из которых является дочерней категорией другой (только хардкор!):
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID
FROM wp_posts
LEFT JOIN wp_term_relationships
ON (wp_posts.ID = wp_term_relationships.object_id)
LEFT JOIN wp_term_relationships AS tt1
ON (wp_posts.ID = tt1.object_id)
LEFT JOIN wp_term_relationships AS tt2
ON (wp_posts.ID = tt2.object_id)
WHERE 1=1
AND ( wp_term_relationships.term_taxonomy_id IN (2,3,4)
AND tt1.term_taxonomy_id IN (1)
AND tt2.term_taxonomy_id IN (3) )
AND wp_posts.post_type = 'post'
AND (wp_posts.post_status = 'publish'
OR wp_posts.post_status = 'acf-disabled'
OR wp_posts.post_status = 'private')
GROUP BY wp_posts.ID
ORDER BY wp_posts.post_date DESC
LIMIT 0, 10
Самое интересное тут (убрал лишнее для наглядности):
WHERE (
wp_term_relationships.term_taxonomy_id IN (2,3,4)
AND
tt1.term_taxonomy_id IN (1)
AND
tt2.term_taxonomy_id IN (3)
)
Какие выводы можно сделать?
1. Под каждый новый термин идет дополнительный LEFT JOIN все той же таблицы wp_term_relationships
2. WHERE использует оператор AND, то есть будут выбраны записи у которых есть все 3 термина
3. Важный нюанс - в первом условии
IN (2,3,4) запрошены и родительская категори (2), так и все ее дочерние (3, 4) - это интересный момент main query на страницах архивов терминов
Итого:
- Первый термин в URL идет основой запроса
- Все последующие докидываются в запрос через LEFT JOIN с использованием оператора AND в WHERE
Значит, работает все именно так, как вам надо. За исключением важного нюанса номер 3 (см. выше). Но это стандартное поведение WP, его можно поменять:
https://wordpress.stackexchange.com/questions/5525...
https://gist.github.com/CodeProKid/1d21fb763514149...
Остается вопрос "как сгенерировать такую ссылку". Это несложно - достаточно склеить адрес сайта, category base, и слаги категорий через +. Пишем простую функцию:
/**
* Generate a link for multiple categories
*
* @param $categories array An array of category slugs
*
* @return string
*/
function my_categories_link( $categories ) {
$category_base = get_option( 'category_base' ) ? get_option( 'category_base' ) : 'category';
$categories_str = implode( '+', $categories );
return sprintf( "%s/%s/%s/",
home_url(),
$category_base,
$categories_str
);
}
В темплейте, там где ссылку надо сделать:
echo my_categories_link( [ 'one', 'two' ] );
Где one и two - слаги нужных категорий.
Можно допилить функцию, чтобы она принимала на выбор - ID, слаги или объекты категорий. Но это уже тонкости :)