Just to start, you say “I am using get_terms to retrieve all terms from Tax 1 with posts associated with it”, however your actual code gets all terms in that taxonomy regardless of whether or not they have posts. You need to set hide_empty
to true
.
So with that out of the way, the bad news: You won’t be able to do this with get_terms()
. That type of information doesn’t exist without querying posts and comparing the terms. So the messy solution you wanted to avoid is unfortunately necessary.
Ultimately I think this is a situation where you might be better off just using SQL. This code will use $wpdb
to get terms from Taxonomy A that have any posts of a given post type that have a specific term in Taxonomy B:
$post_type="post";
$taxonomy_a="post_tag";
$taxonomy_b = 'category';
$term_b_id = 12;
$query = $wpdb->prepare(
"SELECT DISTINCT
terms.*
FROM
`wp_terms` terms
INNER JOIN
`wp_term_taxonomy` tt1 ON
tt1.term_id = terms.term_id
INNER JOIN
`wp_term_relationships` tr1 ON
tr1.term_taxonomy_id = tt1.term_taxonomy_id
INNER JOIN
`wp_posts` p ON
p.ID = tr1.object_id
INNER JOIN
`wp_term_relationships` tr2 ON
tr2.object_ID = p.ID
INNER JOIN
`wp_term_taxonomy` tt2 ON
tt2.term_taxonomy_id = tr2.term_taxonomy_id
WHERE
p.post_type = %s AND
p.post_status="publish" AND
tt1.taxonomy = %s AND
tt2.taxonomy = %s AND
tt2.term_id = %d",
[
$post_type,
$taxonomy_a,
$taxonomy_b,
$term_b_id,
]
);
$results = $wpdb->get_results( $query );
if ( $results ) {
$terms = array_map( 'get_term', $results );
}
So that code gets all Tags that have Posts that are assigned to the Category with the ID 12.
The last little bit with get_term()
ensures that the final array contains the same WP_Term
objects that you would get by running get_terms()
.