Instantly share code, notes, and snippets.
WordPress get related posts - 01
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Get related posts. | |
* | |
* To set the count of posts returned, add a "posts_per_page" value to the $args array. | |
* The default number of posts returned is three. | |
* | |
* @since 1.0.0 | |
* | |
* @param int $post_id A \WP_Post ID. | |
* @param array $args Array of \WP_Query args. | |
* @param $count int The number of posts to retrieve. | |
* | |
* @return array An array of posts. | |
*/ | |
function jr3_get_related_posts( $post_id = 0, $args = array(), $count = 3 ) { | |
// Make sure we have a good post_id. If not, grab the current post. | |
if ( empty( $post_id ) || ! is_numeric( $post_id ) ) { | |
$post_id = get_the_ID(); | |
} | |
// If we still don't have a good ID, bail. | |
if ( empty( $post_id ) ) { | |
return array(); | |
} | |
/* | |
* Start by filtering the input $args. | |
* wp_parse_args() allows us to set default arguments | |
* that can be overriden by input. | |
* | |
* Note that we get the post type of the requested post, | |
* and we set the author of the current post. | |
*/ | |
$args = wp_parse_args( $args, array( | |
'posts_per_page' => 20, // For Sanity. | |
'orderby' => 'title', | |
'post_type' => get_post_type( $post_id ), | |
'post_status' => 'publish', | |
'author' => get_post_field( 'post_author', $post_id ), | |
'no_found_rows' => true, // Speeds up query. | |
) ); | |
/* | |
* Set up taxonomy queries. | |
* This will get us related posts on the same topic(s). | |
*/ | |
$post = get_post( $post_id ); | |
// Get all taxonomies (e.g., "Tags," "Categories") that this post has. | |
$taxonomies = get_object_taxonomies( $post, 'names' ); | |
/* | |
* Sanity check. | |
* Limit the number of taxonomies to prevent getting creating a heavy query. | |
*/ | |
$taxonomies = array_slice( $taxonomies, 0, 3 ); | |
/* | |
* Get each term associated with the post and set | |
* a taxonomy query for it. | |
*/ | |
foreach ( $taxonomies as $taxonomy ) { | |
// Get each term (e.g., single tag or single category) that this post has. | |
$terms = get_the_terms( $post_id, $taxonomy ); | |
if ( empty( $terms ) ) { | |
continue; | |
} | |
// Get the slug of each term in the list. | |
$term_list = wp_list_pluck( $terms, 'slug' ); | |
$args['tax_query'][] = array( | |
'taxonomy' => $taxonomy, | |
'field' => 'slug', | |
'terms' => $term_list, | |
); | |
} | |
/* | |
* If we have more than one taxonomy, use "OR" | |
* to basically say the posts can use any of the terms. | |
* | |
* Otherwise, "AND" will mean we will only look for posts | |
* that contain all of the same terms of the current post, which | |
* can be quite specific and restrictive. | |
*/ | |
if ( isset( $args['tax_query'] ) && count( $args['tax_query'] ) > 1 ) { | |
$args['tax_query']['relation'] = 'OR'; | |
} | |
// Make sure the current post is not part of what we get back. | |
$args['post__not_in'] = array( $post_id ); | |
// Run the query. | |
$query = new WP_Query( $args ); | |
// If we have posts, let's return them. | |
if ( ! empty( $query->posts ) && is_array( $query->posts ) ) { | |
return $query->posts; | |
} | |
// If no posts, return an empty array. | |
return array(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment