Publicações com pelo menos três tags de uma lista de tags

13

Por exemplo, existem as tags { foo, bar, chocolate, mango, hammock, leaf}

Gostaria de encontrar todas as postagens com pelo menos três dessas tags .

Um post com etiquetas { foo, mango, vannilla, nuts, leaf} irá combiná-lo porque tem { foo, mango, leaf} - Assim, pelo menos 3 Tag do conjunto necessária de tags.

Portanto, ele estaria na lista das postagens correspondentes.

Existe uma maneira simples de fazer isso, sem fazer vários loops em todas as postagens?

Cedric
fonte

Respostas:

8

A resposta abaixo é simplificada e pode ser estendida para verificar se alguma postagem tem 3 tags correspondentes antes de exibir a lista. Usando uma consulta e supondo que você tenha pelo menos uma postagem com três tags correspondentes:

//List of tag slugs
$tags = array('foo', 'bar', 'chocolate', 'mango', 'hammock', 'leaf');

$args = array(
    'tag_slug__in' => $tags
    //Add other arguments here
);

// This query contains posts with at least one matching tag
$tagged_posts = new WP_Query($args);

echo '<ul>';
while ( $tagged_posts->have_posts() ) : $tagged_posts->the_post();
   // Check each single post for up to 3 matching tags and output <li>
   $tag_count = 0;
   $tag_min_match = 3;
   foreach ( $tags as $tag ) {
      if ( has_tag( $tag ) && $tag_count < $tag_min_match ) {
         $tag_count ++;
      }
   }
   if ($tag_count == $tag_min_match) {
      //Echo list style here
      echo '<li><a href="'. get_permalink() .'" title="'. get_the_title() .'">'. get_the_title() .'</a></li>';
   }
endwhile;
wp_reset_query();
echo '</ul>';

EDIT: Ajustar a variável $tag_min_matchirá definir o número de correspondências.

stellarcowboy
fonte
2

Aqui está uma maneira de fazer isso:

Dado um conjunto de 5 tags, {a, b, c, d, e}:

1) No PHP, gere todos os subconjuntos possíveis contendo 3 elementos, sem repetição:

{a, b, c}
{a, b, d}
{a, b, e}
{a, c, d}
{a, c, e}
{b, c, d}
{b, c, e}
{c, d, e}

2) Converta esses subconjuntos em uma enorme consulta de taxonomia:

$q = new WP_Query( array(
  'tax_query' => array(
    'relation' => 'OR',
    array(
      'terms' => array( 'a', 'b', 'c' ),
      'field' => 'slug',
      'operator' => 'AND'
    ),
    array(
      'terms' => array( 'a', 'b', 'd' ),
      'field' => 'slug',
      'operator' => 'AND'
    ),
    ...
  )
) );
scribu
fonte
1

A abordagem do sprclldr é a que eu usei. Quanto ao loop while, aqui está o que eu usei:

$relatedPosts = $tagged_posts->posts;
$indexForSort = array();

for ($i = count($relatedPosts) - 1; $i >= 0; $i--) {
  $relatedPostTags = get_tags($relatedPosts[$i]->ID);
  //get the ids of each related post
  $relatedPostTags = $this->my_array_column($relatedPostTags, 'term_id');
  $relatedPostTagsInPostTag = array_intersect($tags, $relatedPostTags);
  $indexForSort[$i] = count($relatedPostTagsInPostTag);
}

//sort by popularity, using indexForSort
array_multisort($indexForSort, $relatedPosts, SORT_DESC);

Depois, pego as principais postagens:

$a_relatedPosts = array_slice($relatedPosts, 0, $this->numberRelatedPosts);

my_array_column é uma função semelhante à array_column do PHP 5,5:

  protected function my_array_column($array, $column) {
    if (is_array($array) && !empty($array)) {
      foreach ($array as &$value) {
        //it also get the object's attribute, not only array's values
        $value = is_object($value) ? $value->$column : $value[$column];
      }
      return $array;
    }
    else
      return array();
  }

Ele não responde à pergunta inicial (mas resolve meu problema de raiz ), como: se não houver postagens relacionadas com três tags comuns, tudo isso fornecerá algumas postagens.

Cedric
fonte