Skip to Content
Menu

related_posts()

Retrieve related posts based on term frequency.

PHP March 5, 2019

Usage

PHP
related_posts($post_id, $args)

Parameters

$post_id
(Required) (int) The post ID to find related posts of
Default: None

$args
(Optional) (array) An array of additional options
Default: None

Parameter Notes

Options for the $args array:

taxonomy
Default: post_tag

post_type
Default: array('post')

max
Default: 5

Request or provide clarification »

Examples

PHP
<h4>Related Posts</h4>
<?php $related_posts = nebula()->related_posts(get_the_id()); ?>
<?php if ( $related_posts->have_posts() ): ?>
        <ul>
            <?php while ( $related_posts->have_posts() ): ?>
                <?php $related_posts->the_post(); ?>
                <li><a href="<?php the_permalink();?>"><h2><?php the_title();?></h2></a></li>
            <?php endwhile; ?>
            <?php wp_reset_postdata(); ?>
        </ul>
<?php endif; ?>

Additional Notes

Results are stored in a transient for 24 hours for optimization.

Was this page helpful? Yes No


    A feedback message is required to submit this form.


    Please check that you have entered a valid email address.

    Enter your email address if you would like a response.

    Thank you for your feedback!

    Source File

    Located in /libs/Functions.php on line 1832.

    No Hooks

    This function does not have any filters or actions available. Request one?
    PHP
            public function related_posts($post_id=null, $args=array()){
                $this->timer('Related Posts');
    
                global $post, $wpdb;
    
                $post_id = intval($post_id);
                if ( !$post_id && $post->ID ){
                    $post_id = $post->ID;
                }
    
                if ( !$post_id ){
                    return false; //Post ID is required for this function
                }
    
                $defaults = array(
                    'taxonomy' => 'post_tag',
                    'post_type' => array('post'),
                    'max' => 5
                );
                $options = wp_parse_args($args, $defaults);
    
                $related_post_ids = nebula()->transient('nebula-related-' . $options['taxonomy'] . '-' . $post_id, function($data){
                    $term_args = array(
                        'fields' => 'ids',
                        'orderby' => 'count', //Sort by frequency
                        'order' => 'ASC' //Least popular to most popular
                    );
    
                    $orig_terms_set = wp_get_object_terms($data['post_id'], $data['options']['taxonomy'], $term_args);
                    $orig_terms_set = array_map('intval', $orig_terms_set); //Make sure each returned term id to be an integer.
                    $terms_to_iterate = $orig_terms_set; //Store a copy that we'll be reducing by one item for each iteration.
    
                    $post_args = array(
                        'fields' => 'ids',
                        'post_type' => $data['options']['post_type'],
                        'post__not_in' => array($data['post_id']),
                        'posts_per_page' => 50 //Start with more than enough posts
                    );
    
                    $related_post_ids = array();
    
                    //Loop through the terms to find posts that contain multiple terms (term1 AND term2 AND term3)
                    while ( count($terms_to_iterate) > 1 ){
                        $post_args['tax_query'] = array(
                            array(
                                'taxonomy' => $data['options']['taxonomy'],
                                'field' => 'id',
                                'terms' => $terms_to_iterate,
                                'operator' => 'AND'
                            )
                        );
    
                        $posts = get_posts($post_args);
                        foreach( $posts as $id ){
                            $id = intval($id);
                            if ( !in_array($id, $related_post_ids) ){
                                $related_post_ids[] = $id;
                            }
                        }
    
                        array_pop($terms_to_iterate); //Remove the least related post ID
                    }
    
                    $post_args['posts_per_page'] = $data['options']['max']; //Reduce the number to our desired max
                    $post_args['tax_query'] = array(
                        array(
                            'taxonomy' => $data['options']['taxonomy'],
                            'field' => 'id',
                            'terms' => $orig_terms_set
                        )
                    );
    
                    //Check for posts that contain any of the terms (to fill out the desired max)
                    $posts = get_posts($post_args);
                    foreach ( $posts as $count => $id ){
                        $id = intval($id);
                        if ( !in_array($id, $related_post_ids) ){
                            $related_post_ids[] = $id;
                        }
    
                        if ( count($related_post_ids) > $data['options']['max'] ){
                            break; //We have enough related post IDs now, stop the loop.
                        }
                    }
    
                    return $related_post_ids;
                }, array('options' => $options, 'post_id' => $post_id), DAY_IN_SECONDS);
    
                if ( !$related_post_ids ){
                    $this->timer('Related Posts', 'end');
                    return false;
                }
    
                //Query for the related post IDs
                $query_options = array(
                    'post__in' => $related_post_ids,
                    'orderby' => 'post__in',
                    'post_type' => $options['post_type'],
                    'posts_per_page' => min(array(count($related_post_ids), $options['max'])),
                );
    
                $this->timer('Related Posts', 'end');
                return new WP_Query($query_options);
            }
    

    Override

    This function can not be short-circuited with an override filter. Request one?