it-swarm.com.de

Verwandte Beiträge von mehreren Tags?

Ich war neugierig, ob es möglich war, verwandte Beiträge mit mehreren Tags anzuzeigen.

Die Seite, an der ich arbeite, hat ungefähr 5 Tags pro Post. Die meisten Beiträge haben 1 oder 2 Tags gemeinsam. Die verwandten Posts, die ich gerne zeigen würde, haben 3-5 gemeinsame Tags.

Ich möchte also, dass die verwandten Beiträge funktionieren, indem ich nach Beiträgen mit der größten Anzahl gemeinsamer Tags suche und sie in absteigender Reihenfolge anzeige.

Angenommen, ich zeige 3 verwandte Posts an: relatedpost1 hat 4 gemeinsame Tags, relatedpost2 hat 3 gemeinsame Tags und relatedpost3 hat 1 gemeinsame Tags.

Ist das überhaupt möglich?

Im Moment spiele ich mit zwei Möglichkeiten, die Beiträge anzuzeigen, aber sie funktionieren nicht so, wie ich es gerne hätte:

Die erste Methode ( code ) zeigt nur Posts mit ALLEN gemeinsamen Tags an.

<?php $orig_post = $post;
global $post;
$tags = wp_get_post_tags($post->ID);
if ($tags) {
$tag_ids = array();
foreach($tags as $individual_tag) $tag_ids[] = $individual_tag->term_id;
$args=array(
'tag__in' => $tag_ids,
'post__not_in' => array($post->ID),
'posts_per_page'=>3, // Number of related posts that will be shown.
'caller_get_posts'=>1
);
$my_query = new wp_query( $args );
if( $my_query->have_posts() ) {
echo '<div id="relatedposts"><h3>Related Posts</h3><div class="relatedbreak"></div><ul id="relatedul">';
while( $my_query->have_posts() ) {
$my_query->the_post(); ?>
<li><div class="relatedthumb"><a href="<? the_permalink()?>" rel="bookmark" title="<?php the_title(); ?>"><?php the_post_thumbnail(array(185, 185)); ?></a></div>
<div class="relatedcontent">
<center><a href="<? the_permalink()?>" rel="bookmark" title="<?php the_title(); ?>"><div class="comments_text"><?php the_title(); ?></div></center></a>
</div>
</li>
<? }
echo '</ul></div>';
}
}
$post = $orig_post;
wp_reset_query(); ?>`

Die zweite Methode ( code ) zeigt nur Posts mit dem ersten gemeinsamen Tag an.

<?php
//for use in the loop, list 5 post titles related to first tag on current post
$tags = wp_get_post_tags($post->ID);
if ($tags) {
echo '<div id="relatedposts"><h3>Related Posts</h3></div><div class="relatedbreak"></div>';
$first_tag = $tags[0]->term_id;
$args=array(
'tag__in' => array($first_tag),
'post__not_in' => array($post->ID),
'posts_per_page'=>3,
'caller_get_posts'=>1
);
$my_query = new WP_Query($args);
if( $my_query->have_posts() ) {
while ($my_query->have_posts()) : $my_query->the_post(); ?>
<ul id="relatedul">
<li><div class="relatedthumb"><a href="<? the_permalink()?>" rel="bookmark" title="<?php the_title(); ?>"><?php the_post_thumbnail(array(185, 185)); ?></a></div>
<a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>"><div class="comments_text"><?php the_title(); ?></div></a></li>
</ul>
<?php
endwhile;
}
wp_reset_query();
}
?>

Beide Arten von saugen; Ich erhalte entweder ziemlich zufällige Anzeigen von Posts (da die meisten meiner Posts mindestens 1 Tag gemeinsam haben) oder (für einige Posts) keine verwandten Posts (da ihre gemeinsamen Tags Tag 4 oder 5 sind).

Jede Hilfe wäre sehr dankbar.

4
Jacob

Ich hatte die gleiche Idee und schrieb ein kleines Plugin, um mir dabei zu helfen.

function get_pew_related_data($args, $post_id, $related_id) {
    global $post, $wpdb;
    $post_id = intval( $post_id );
    if( !$post_id && $post->ID ) {
        $post_id = $post->ID;
    }

    if( !$post_id ) {
        return false;
    }

    $defaults = array(
        'taxonomy' => 'topics',
        'post_type' => array('post'),
        'max' => 5
    );
    $options = wp_parse_args( $args, $defaults );

    $transient_name = 'pew-related-' . $options['taxonomy'] . '-' . $post_id;

    if( isset($_GET['flush-related-links']) && is_user_logged_in() ) {
        echo '<p>Related links flushed! (' . $transient_name . ')</p>';
        delete_transient( $transient_name );
    }

    $output = get_transient( $transient_name );
    if( $output !== false && !is_preview() ) {
        //echo $transient_name . ' read!';
        return $output;
    } 

    $args = array(
        'fields' => 'ids',
        'orderby' => 'count',
        'order' => 'ASC'
    );
    $orig_terms_set = wp_get_object_terms( $post_id, $options['taxonomy'], $args );

    //Make sure each returned term id to be an integer.
    $orig_terms_set = array_map('intval', $orig_terms_set);

    //Store a copy that we'll be reducing by one item for each iteration. 
    $terms_to_iterate = $orig_terms_set;

    $post_args = array(
        'fields' => 'ids',
        'post_type' => $options['post_type'],
        'post__not_in' => array($post_id),
        'posts_per_page' => 50
    );
    $output = array();
    while( count( $terms_to_iterate ) > 1 ) {

        $post_args['tax_query'] = array(
            array(
                'taxonomy' => $options['taxonomy'],
                'field' => 'id',
                'terms' => $terms_to_iterate,
                'operator' => 'AND'
            )
        );

        $posts = get_posts( $post_args );

        /*
        echo '<br>';
        echo '<br>';
        echo $wpdb->last_query;
        echo '<br>';
        echo 'Terms: ' . implode(', ', $terms_to_iterate);
        echo '<br>';
        echo 'Posts: ';
        echo '<br>';
        print_r( $posts );
        echo '<br>';
        echo '<br>';
        echo '<br>';
        */

        foreach( $posts as $id ) {
            $id = intval( $id );
            if( !in_array( $id, $output) ) {
                $output[] = $id;
            }
        }
        array_pop( $terms_to_iterate );
    }

    $post_args['posts_per_page'] = 10;
    $post_args['tax_query'] = array(
        array(
            'taxonomy' => $options['taxonomy'],
            'field' => 'id',
            'terms' => $orig_terms_set
        )
    );

    $posts = get_posts( $post_args );

    foreach( $posts as $count => $id ) {
        $id = intval( $id );
        if( !in_array( $id, $output) ) {
            $output[] = $id;
        }
        if( count($output) > $options['max'] ) {
            //We have enough related post IDs now, stop the loop.
            break;
        }
    }

    if( !is_preview() ) {
        //echo $transient_name . ' set!';
        set_transient( $transient_name, $output, 24 * HOUR_IN_SECONDS );
    }

    return $output;
}

function pew_related( $args = array(), $post_id = '', $related_id = '' ) {
    $post_ids = get_pew_related_data( $args, $post_id, $related_id );

    if( !$post_ids ) {
        return false;
    }

    $defaults = array(
        'post__in' => $post_ids,
        'orderby' => 'post__in',
        'post_type' => array('post'),
        'posts_per_page' => min( array(count($post_ids), 10)),
        'related_title' => 'Related Posts'
    );
    $options = wp_parse_args( $args, $defaults );

    $related_posts = new WP_Query( $options );
    if( $related_posts->have_posts() ):
    ?>
    <h5><?=$options['related_title']?></h5>
    <div id="related-material" class="promo">
        <?php while ( $related_posts->have_posts() ):
            $related_posts->the_post();
        ?>
            <a class="post" href="<?=the_permalink();?>">
                <div class="meta">
                    <?php
                    $post_project = wp_get_object_terms($related_posts->post->ID, 'projects');
                    $project = 'Pew Research Center';
                    $project_slug = '';
                    if( isset($post_project[0]) ) {
                        $project = $post_project[0]->name;
                        $project_slug =  $post_project[0]->slug;
                    } elseif( $related_posts->post->post_type == 'fact-tank' ) {
                        $project = 'Fact Tank';
                        $project_slug = 'fact-tank';
                    }
                    ?>
                    <span class="project <?=$project_slug;?> right-seperator"><?=$project;?></span>
                    <span class="date"><?php the_time('M j, Y'); ?></span>
                </div>
                <h2><?=the_title();?></h2>
            </a>
        <?php endwhile;
            wp_reset_postdata();

         ?> 
    </ol>
    </div>
    <?php
    endif;

}

Es wird nach Beiträgen mit gemeinsamen Begriffen gesucht, und die Begriffe werden nach Häufigkeit sortiert, sodass die am wenigsten verwendeten Begriffe zuerst und dann die am häufigsten verwendeten Begriffe angezeigt werden. Die erste Funktion ruft die Daten ab und speichert sie in einer Übergangsphase, damit die Ergebnisse nicht unnötigerweise immer wieder neu ausgeführt werden. Die zweite Funktion gibt nur die Ausgabe wieder. Dies ist es, was unsere verwandten Posts auf einer unserer Sites bei der Arbeit antreibt http://www.pewresearch.org/fact-tank/2013/08/02/both-parties-underwater-heading-into-2014-elections/

Der Algorithmus funktioniert folgendermaßen:

  1. Holen Sie sich alle Begriffe aus dem Beitrag nach Anzahl in aufsteigender Reihenfolge (am wenigsten beliebt zu beliebter)
  2. Durchlaufen Sie diesen Satz von Begriffen und suchen Sie nach Posts, die Term1 UND Term2 UND Term3 enthalten
  3. Entfernen Sie bei jeder Iteration den am wenigsten verbreiteten Begriff aus der Liste, um die Ergebnisse zu erweitern, bis die gewünschte Anzahl von Beiträgen erreicht ist oder nur noch ein Begriff zu überprüfen ist.
  4. Wenn wir immer noch nicht genügend Posts haben, um unsere Anforderungen zu erfüllen, suchen Sie nach Posts, die Term1 OR Term2 OR Term3 enthalten
  5. Speichern Sie das Ergebnis in einem Transienten, damit wir diese Abfragen für eine Weile nicht erneut ausführen müssen.

Hoffe das hilft dir weiter.

4
kingkool68

Danke @Dero. Bitte denken Sie daran, das Datenbankpräfix richtig einzustellen:

function exe_get_related_posts_by_common_terms( $post_id, $number_posts = 0, $taxonomy = 'post_tag', $post_type = 'post' ) {
    global $wpdb;

    $post_id = (int) $post_id;
    $number_posts = (int) $number_posts;

    $limit = $number_posts > 0 ? ' LIMIT ' . $number_posts : '';

    $related_posts_records = $wpdb->get_results(
        $wpdb->prepare(
            "SELECT tr.object_id, count( tr.term_taxonomy_id ) AS common_tax_count
             FROM {$wpdb->term_relationships} AS tr
             INNER JOIN {$wpdb->term_relationships} AS tr2 ON tr.term_taxonomy_id = tr2.term_taxonomy_id
             INNER JOIN {$wpdb->term_taxonomy} as tt ON tt.term_taxonomy_id = tr2.term_taxonomy_id
             INNER JOIN {$wpdb->posts} as p ON p.ID = tr.object_id
             WHERE
                tr2.object_id = %d
                AND tt.taxonomy = %s
                AND p.post_type = %s
             GROUP BY tr.object_id
             HAVING tr.object_id != %d
             ORDER BY common_tax_count DESC" . $limit,
            $post_id, $taxonomy, $post_type, $post_id
        )
    );

    if ( count( $related_posts_records ) === 0 )
        return false;

    $related_posts = array();

    foreach( $related_posts_records as $record )
        $related_posts[] = array(
            'post_id' => (int) $record->object_id,
            'common_tax_count' => $record->common_tax_count
        );

    return $related_posts;
}

Es funktioniert also auf allen Systemen hervorragend.

0
endcoreCL

Ich denke nicht, dass query_posts() oder new WP_Query() hier etwas Gutes bewirken werden. Sie müssen die Datenbank direkt abfragen. Hier ist die Methode, die ich geschrieben habe, um das zu erreichen, was Sie anscheinend brauchen:

/*
 * Returns related posts to a given post based on a specific taxonomy
 * By default, this method returns list of posts with the highest number of common tags
 *
 * var $post_id - the reference post for which we want to get the list of similar posts
 * var $number_posts - max how many related posts to return, 0 for unlimited
 * var $taxonomy - which taxonomy to use to determine related posts ( 'post_tag' or 'category' are the basic examples )
 * var $post_type - change to a custom post_type if you want to get related posts of another post type
 */
function exe_get_related_posts_by_common_terms( $post_id, $number_posts = 0, $taxonomy = 'post_tag', $post_type = 'post' ) {

    global $wpdb;

    $post_id = (int) $post_id;
    $number_posts = (int) $number_posts;

    $limit = $number_posts > 0 ? ' LIMIT ' . $number_posts : '';

    $related_posts_records = $wpdb->get_results(
        $wpdb->prepare(
            "SELECT tr.object_id, count( tr.term_taxonomy_id ) AS common_tax_count
             FROM wp_term_relationships AS tr
             INNER JOIN wp_term_relationships AS tr2 ON tr.term_taxonomy_id = tr2.term_taxonomy_id
             INNER JOIN wp_term_taxonomy as tt ON tt.term_taxonomy_id = tr2.term_taxonomy_id
             INNER JOIN wp_posts as p ON p.ID = tr.object_id
             WHERE
                tr2.object_id = %d
                AND tt.taxonomy = %s
                AND p.post_type = %s
             GROUP BY tr.object_id
             HAVING tr.object_id != %d
             ORDER BY common_tax_count DESC" . $limit,
             $post_id, $taxonomy, $post_type, $post_id
        )
    );

    if ( count( $related_posts_records ) === 0 )
        return false;

    $related_posts = array();

    foreach( $related_posts_records as $record )
        $related_posts[] = array(
            get_post( (int) $record->object_id ),
            'common_tax_count' => $record->common_tax_count
        );

    return $related_posts;

}

Die Methode dient zum Abrufen verwandter Posts basierend auf einer einzelnen Taxonomie, standardmäßig auf der Taxonomie 'post_tag'. Beiträge werden nach der Anzahl der gebräuchlichen Begriffe vom höchsten zum niedrigsten sortiert. Um verwandte Posts für mehrere gebräuchliche Taxonomien gleichzeitig abzurufen, müssten Sie AND tt.taxonomy = %s auf AND ( tt.taxonomy = 'post_tag' OR tt.taxonomy = 'category' ) einstellen. Gleiches gilt, wenn Sie Beiträge verschiedener Beitragstypen abrufen möchten.

0
Dero