You can simple run a foreach
loop and exclude the terms from your returned array of terms. Just a few notes
-
cat
accepts a string or integer value, not and array -
category__not_in
should be an array
Here is a modified version of a related posts function I recently did here. Please go and check it out and check out how the $args
parameter should be used, just remember, it has moved to the third paremeter in the new function 😉
Here is the code (I have commented the code so you can follow it, it is untested though and requires PHP 5.4+)
function get_related_posts( $taxonomy = '', $exclude = [], $args = [] )
{
/*
* Before we do anything and waste unnecessary time and resources, first check if we are on a single post page
* If not, bail early and return false
*/
if ( !is_single() )
return false;
/*
* Check if we have a valid taxonomy and also if the taxonomy exists to avoid bugs further down.
* Return false if taxonomy is invalid or does not exist
*/
if ( !$taxonomy )
return false;
$taxonomy = filter_var( $taxonomy, FILTER_SANITIZE_STRING );
if ( !taxonomy_exists( $taxonomy ) )
return false;
/*
* We have made it to here, so we should start getting our stuff togther.
* Get the current post object to start of
*/
$current_post = get_queried_object();
/*
* Get the post terms
*/
$terms = get_the_terms( $current_post->ID, $taxonomy );
/*
* Lets only continue if we actually have post terms and if we don't have an WP_Error object. If not, return false
*/
if ( !$terms || is_wp_error( $terms ) )
return false;
// Define our array to hold the term id'saveHTML
$term_ids = [];
foreach ( $terms as $term ) {
// Check if we have terms to exclude and exclude them
if ( $exclude ) {
if ( in_array( $term->id, $exclude ) )
continue;
} else {
$term_ids[] = (int) $term->term_id;
}
/*
* Set the default query arguments
*/
$defaults = [
'post_type' => $current_post->post_type,
'post__not_in' => [$current_post->ID],
'tax_query' => [
[
'taxonomy' => $taxonomy,
'terms' => $term_ids,
'include_children' => false
],
],
];
/*
* Validate and merge the defaults with the user passed arguments
*/
if ( is_array( $args ) ) {
$args = wp_parse_args( $args, $defaults );
} else {
$args = $defaults;
}
return $q;
}
You would use it as follow then
if ( function_exists( 'get_related_posts' ) ) {
$related_posts = get_related_posts(
'my_taxonomy_name', // Taxonomy name, if build in, in should be 'category'
[1, 2, 3] // Array of terms to exclude
);
if ( $related_posts ) {
foreach ( $related_posts as $post ) {
setup_postdata( $post );
// Use your template tags and html mark up as normal like
the_title();
the_content();
// etc etc
}
wp_reset_postdata();
}
}