Sort wordpress posts by the amount of shared tags with current post

Here is where my code is at so far. It pulls in all posts that share tags with the current post, but I can’t figure out how to sort them in a descending fashion where the first posts shares the most tags with the current post. Any ideas would be appreciated!

$tags = wp_get_post_tags( $post->ID, 'Asset' );
if ( $tags ) {
    $tag_ids = array();
    foreach( $tags as $individual_tax ) $tag_ids[] = $individual_tax->term_id;
    $args = array(
        'tag__in' => $tag_ids,
        'post_type' => 'Asset',
        'post__not_in'          => array( $post->ID ),
        'posts_per_page'        => 3,
    );

    $my_query = new wp_query( $args );

    if( $my_query->have_posts() ) {
        while ( $my_query->have_posts() ){
            $my_query->the_post();

            get_template_part( 'asset' );

        }
    }

    wp_reset_query();

}

Updated Code:

Read More
$tags = wp_get_post_tags( $post->ID, 'Asset' );
if ( $tags )  {
$tag_ids = array();
foreach( $tags as $individual_tax ) $tag_ids[] = $individual_tax->term_id;
$args = array(
    'tag__in' => $tag_ids,
    'post_type' => 'Asset',
    'post__not_in'          => array( $post->ID ),
    'posts_per_page'        => 3,
);

function order_results($post1, $post2) {

    $tags1 = wp_get_post_tags($post1);
    $tags2 = wp_get_post_tags($post1);

    $tag_cnt1 = 0;
    $tag_cnt2 = 0;
    foreach ($tags1 as $tag) {
        if (in_array($tag->term_id, $tag_ids)) {

        }
    }
    foreach ($tags2 as $tag) {
        if (in_array($tag->term_id, $tag_ids)) {
            ++$tag_cnt2;
        }
    }

    return ($tag_cnt1 < $tag_cnt2) ? -1 : 1;

}

$my_query = new wp_query( $args );
$posts = $my_query->posts;

// Sort
usort( $posts, 'order_results');

// Print
foreach ($posts as $post) {                     

    get_template_part( 'asset' );

}

wp_reset_query();

}

Final Working Code:

$tags = wp_get_post_tags( $post->ID, 'Asset' );
if ( $tags )  {
$tag_ids = array();
foreach( $tags as $individual_tax ) $tag_ids[] = $individual_tax->term_id;
$args = array(
    'tag__in' => $tag_ids,
    'post_type' => 'Asset',
    'post__not_in'          => array( $post->ID ),
    'posts_per_page'        => 3,
);

// Sort
function order_results($post1, $post2) {
    //Get current post tags
    global $tag_ids;

    // Reduce down to tags ids
    $tags1 = wp_get_post_tags($post1->ID);
    $tags2 = wp_get_post_tags($post2->ID);
    $tags_num_1 = array();
    $tags_num_2 = array();

    foreach( $tags1 as $tags ) $tags_num_1[] = $tags->term_id;
    foreach( $tags2 as $tags ) $tags_num_2[] = $tags->term_id;

    // Set tag count
    $tag_cnt1 = 0;
    $tag_cnt2 = 0;

    // Count tags
    foreach ($tags_num_1 as $tag) {
        if (in_array($tag, $tag_ids)) {
            $tag_cnt1++;
        }
    }
    foreach ($tags_num_2 as $tag) {
        if (in_array($tag, $tag_ids)) {
            $tag_cnt2++;
        }
    }

    // Order
    return ($tag_cnt1 < $tag_cnt2) ? 1 : -1;

}

$my_query = new wp_query( $args );
$posts = $my_query->posts;

usort( $posts, 'order_results');


// Print
foreach ($posts as $post) {                     
    setup_postdata( $post );

    get_template_part( 'asset' );

}

wp_reset_query();

}

Related posts

Leave a Reply

1 comment

  1. WP_Query does not allow you to specify an arbitrary sort criteria. You would need to sort the results afterwards, e.g.

    function order_results($post1, $post2) {
        $tags1 = wp_get_post_tags($post1->ID);
        $tags2 = wp_get_post_tags($post2->ID);
        $tag_cnt1 = 0;
        $tag_cnt2 = 0;
        foreach ($tags1 as $tag) {
            if (in_array($tag->term_id, $tag_ids)) {
    
            }
        }
        foreach ($tags2 as $tag) {
            if (in_array($tag->term_id, $tag_ids)) {
                ++$tag_cnt2;
            }
        }
        return ($tag_cnt1 < $tag_cnt2) ? -1 : 1;
    }
    
    usort( $my_query->posts, 'order_results');