As I can understand, cpt_tag is only assigned to the custom post type cpt. This makes things much easier and less complicated. You do not need two queries and you don’t need to merge anything
Here is the plan:
-
We need to know which terms you need to show on the homepage from the
cptpost type -
Using
get_terms()and theexcludeparameter, we will exclude the terms we need to show posts from from thecptpost type. The returned array fromget_terms()will hold all the terms we don’t want to show. We are also going to set thefieldsparameter toidsso that we get an array of term ids -
This array will be passed to the
tax_queryinpre_get_posts. As this is terms we need to exclude, we will set theoperatorparameter toNOT INto exclude posts with these terms
You need only minor adjustments to your code to make this work
Here is an example
add_action( 'pre_get_posts', 'get_posts_plus_cpt_with_certain_tag' );
function get_posts_plus_cpt_with_certain_tag( $query ) {
if ( $query->is_home() && $query->is_main_query() ) {
/*
* Change 110 to the term id you need to display posts from from cpt post type
*/
$terms = get_terms( 'cpt_tag', array( 'exclude' => 110, 'fields' => 'ids' ) );
if ( $terms && !is_wp_error( $terms ) ) {
$taxquery = array(
array(
'taxonomy' => 'cpt_tag',
'field' => 'term_id',
'terms' => $terms,
'operator' => 'NOT IN'
)
);
$query->set('tax_query', $taxquery);
}
$query->set( 'post_type', array( 'post', 'cpt' ) );
}
}
EDIT 1
I did not include safety, you should first check if you get any results from get_terms before using it. I have included that in my code now
EDIT 2
The above solution works, but there is a small glitch as pointed out in comments
…if I have
cptpost type posts that have nocpt_tags at all, thetax_querydoesn’t filter them out, it only filters outcptpost type posts with at least onecpt_tag…
The problem arises in the fact that custom post type posts by default doesn’t have a default term assigned to it when no term is assigned to them in the same way as normal post type post have the term uncategorized assigned to them by default when no term is assigned to it
Because there is no relation to any term if no term is assigned to them, custom post type posts does not appear in the wp_term_relationships table, so they don’t appear in a normal tax_query
To work around this issue, we need to slightly alter our original workflow. Here is how we are going to tackle this issue
-
Get all the terms assigned to the
postpost type. By default, all posts from thepostpost type will have at least one term assigned to it unless this behavior is altered by some other drastic code. So we are 99.999% safe here. -
We are going to use the same strategy as previous but with a slight modification. We will still use
get_terms()with thefieldsparameter set toids, but here we will get all the terms. I will assume that you are using the default build-in taxonomycategoryfor thepostpost type. -
We can simply just pass the term ids we need to include for the
cpt_tagto ourtax_query, nothing special here -
Remember to set the
relationparameter toORas we need posts with all terms incategorytaxonomy or all posts that has the specific term from thecpt_tagtaxonomy. Omitting therelationparameter will default toANDwhich will fail your query as it will look for posts that have terms incategorytaxonomy andcpt_tagtaxonomy
So lets put that in code:
(I will again use term id 110 for the term for cpt_tag, just change accordingly)
add_action( 'pre_get_posts', 'get_posts_plus_cpt_with_certain_tag' );
function get_posts_plus_cpt_with_certain_tag( $query ) {
if ( $query->is_home() && $query->is_main_query() ) {
/*
* Change 110 to the term id you need to display posts from from cpt post type
*/
$terms = get_terms( 'category', array( 'fields' => 'ids' ) );
if ( $terms && !is_wp_error( $terms ) ) {
$taxquery = array(
'relation' => 'OR',
array( // Includes all terms (categories) for post post type
'taxonomy' => 'category',
'field' => 'term_id',
'terms' => $terms,
),
array( // Include the terms you need to display from cpt_tag
'taxonomy' => 'cpt_tag',
'field' => 'term_id',
'terms' => array( 110 ),
),
);
$query->set('tax_query', $taxquery);
}
$query->set( 'post_type', array( 'post', 'cpt' ) );
}
}