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
cpt
post type -
Using
get_terms()
and theexclude
parameter, we will exclude the terms we need to show posts from from thecpt
post type. The returned array fromget_terms()
will hold all the terms we don’t want to show. We are also going to set thefields
parameter toids
so that we get an array of term ids -
This array will be passed to the
tax_query
inpre_get_posts
. As this is terms we need to exclude, we will set theoperator
parameter toNOT IN
to 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
cpt
post type posts that have nocpt_tag
s at all, thetax_query
doesn’t filter them out, it only filters outcpt
post 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
post
post type. By default, all posts from thepost
post 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 thefields
parameter set toids
, but here we will get all the terms. I will assume that you are using the default build-in taxonomycategory
for thepost
post type. -
We can simply just pass the term ids we need to include for the
cpt_tag
to ourtax_query
, nothing special here -
Remember to set the
relation
parameter toOR
as we need posts with all terms incategory
taxonomy or all posts that has the specific term from thecpt_tag
taxonomy. Omitting therelation
parameter will default toAND
which will fail your query as it will look for posts that have terms incategory
taxonomy andcpt_tag
taxonomy
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' ) );
}
}