Skip to content

Instantly share code, notes, and snippets.

@eteubert
Created June 15, 2012 09:59
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save eteubert/2935700 to your computer and use it in GitHub Desktop.
Save eteubert/2935700 to your computer and use it in GitHub Desktop.
WordPress: Similar posts by matching tags
<?php
/**
* Return posts with maximum age of one year.
*
* Usage:
* add_filter( 'posts_where', 'wp_query_filter_max_one_year_old' );
* $my_query = new WP_Query( array( ... ) );
* remove_filter( 'posts_where', 'wp_query_filter_max_one_year_old' );
*
* @param string $where
* @return string
*/
function wp_query_filter_max_one_year_old( $where = '' ) {
$where .= " AND post_date > '" . date( 'Y-m-d', strtotime( '-356 days' ) ) . "'";
return $where;
}
/**
* Find similar posts based on tags.
*
* @param int $post_id
* @param integer $limit maximum number of posts
* @param integer $cache_duration time to cache in seconds. default: 1 week
* @return array list of post_ids
*/
function get_similar_post_ids_by_tags( $post_id = NULL, $limit = 3, $cache_duration = 604800 ) {
if ( ! $post_id )
$post_id = get_the_ID();
$cache_key = "inps_similar_" . $post_id;
if ( false === ( $scores = get_transient( $cache_key ) ) ) {
$tags = wp_get_post_tags( $post_id );
// fetch all last years posts with at least one matching tag
$tag_ids = array_map( function( $t ) { return $t->term_id; }, $tags );
add_filter( 'posts_where', 'wp_query_filter_max_one_year_old' );
$args = array(
'tag__in' => $tag_ids,
'post__not_in' => array( $post_id ),
'posts_per_page' => -1
);
$query_similar_posts = new WP_Query( $args );
remove_filter( 'posts_where', 'wp_query_filter_max_one_year_old' );
$scores = array();
// count identical tags for each post
while ( $query_similar_posts->have_posts() ) {
$p = $query_similar_posts->next_post();
$identical_tags = 0;
$this_tags = wp_get_post_tags( $p->ID );
foreach ( $this_tags as $t ) {
if ( in_array( $t->term_id, $tag_ids ) ) {
$identical_tags++;
}
}
if ( $identical_tags > 0 ) {
$scores[] = array( 'post_id' => $p->ID, 'score' => $identical_tags );
}
}
// sort by score
usort( $scores, function ( $a, $b ) {
if ( $a[ 'score' ] == $b[ 'score' ] ) {
return 0;
}
return ( $a[ 'score' ] > $b[ 'score' ] ) ? -1 : 1;
} );
// take first $limit only
$scores = array_slice( $scores, 0, $limit );
// return without scores
$scores = array_map( function( $p ){ return $p[ 'post_id' ]; }, $scores );
set_transient( $cache_key, $scores, $cache_duration );
}
return $scores;
}
?>
<!-- Example for Theme file -->
<?php $similar_posts = get_similar_post_ids_by_tags(); ?>
<strong><?php __( 'Related Posts' ) ?></strong>
<ul>
<?php foreach ( $similar_posts as $similar_post_id ): ?>
<li>
<a href="<?php echo get_permalink( $similar_post_id ); ?>"><?php echo get_the_title( $similar_post_id ); ?></a>
</li>
<?php endforeach; ?>
</ul>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment