Taxonomie personnalisée WP_Query pour tous les termes d'une taxonomie?

8

Existe-t-il un moyen simple de rechercher des publications qui sont étiquetées avec n'importe quel terme d'une taxonomie particulière?

Je connais cette technique:

$custom_taxonomy_query = new WP_Query( 
 array(
  'taxonomy_name' => 'term_slug',
 )
);

Mais je voudrais soit passer un caractère générique à la place de term_slug, ou peut-être juste une chaîne vide. Ensuite, cela me donnerait tous les messages qui sont étiquetés par n'importe quel terme de cette taxonomie, pas seulement un terme spécifique.

Merci pour votre aide, Dave

Dave Morris
la source

Réponses:

23

J'ai rencontré une situation similaire, Dave. Ce code a fait l'affaire à mes fins. Ce n'est pas l'option la plus légère au monde, mais elle fait bien le travail:

// Get all term ID's in a given taxonomy
$taxonomy = 'taxonomy_name';
$taxonomy_terms = get_terms( $taxonomy, array(
    'hide_empty' => 0,
    'fields' => 'ids'
) );

// Use the new tax_query WP_Query argument (as of 3.1)
$taxonomy_query = new WP_Query( array(
    'tax_query' => array(
        array(
            'taxonomy' => $taxonomy,
            'field' => 'id',
            'terms' => $taxonomy_terms,
        ),
    ),
) );

J'espère que cela vous aidera, vous ou toute autre personne rencontrant le problème.

Kevin

Kevin Leary
la source
Cela m'a été extrêmement utile. Merci @kevinlearynet
Tyrun
Toujours relatif aujourd'hui
user1676224
7

Quelque chose comme ça pourrait fonctionner:

$ args = tableau (
    'post_type' => 'post',
    'tax_query' => tableau (
        tableau (
            'taxonomy' => 'your_custom_taxonomy',
            'operator' => 'EXISTS'
        ),
    ),
);
$ query = new WP_Query ($ args);

Vous demandez essentiellement un article attribué à un terme quelconque dans votre_custom_taxonomy.

laurenfs132
la source
4

Salut @Dave Morris:

Vous avez raison, WordPress décide que si vous n'avez pas de terme, il ignorera simplement votre taxonomie.

Il y a trois (3) approches que vous pourriez essayer:

  1. Utilisez une requête SQL complète avec $wpdb->get_results(),

  2. Obtenez une liste de $post->IDs pour tous les messages de votre taxonomie, puis passez-les à l'aide de l' 'post__id'argument, ou

  3. Annotez le SQL utilisé parWP_Query avec l'un des crochets qui vous permettent d'ajouter un SQL INNER JOINréférençant les tables de taxonomie.

J'essaie d'éviter SQL complet dans WordPress jusqu'à ce que cela ne puisse pas être aidé ou qu'il renvoie simplement une liste d'ID. Et dans ce cas, j'éviterais de tirer une liste de $post-IDs à utiliser avec l' 'post__id'argument, car cela pourrait entraîner des problèmes de performances et même des problèmes de mémoire si vous aviez beaucoup de messages. Cela nous laisse donc avec # 3.

J'ai créé une classe à étendreWP_Query appelée PostsByTaxonomyqui utilise le 'posts_joincrochet. Tu peux le voir ici:

class PostsByTaxonomy extends WP_Query {
  var $posts_by_taxonomy;
  var $taxonomy;
  function __construct($args=array()) {
    add_filter('posts_join',array(&$this,'posts_join'),10,2);
    $this->posts_by_taxonomy = true;
    $this->taxonomy = $args['taxonomy'];
    unset($args['taxonomy']);
    parent::query($args);
  }
  function posts_join($join,$query) {
    if (isset($query->posts_by_taxonomy)) {
      global $wpdb;
      $join .=<<<SQL
INNER JOIN {$wpdb->term_relationships} ON {$wpdb->term_relationships}.object_id={$wpdb->posts}.ID
INNER JOIN {$wpdb->term_taxonomy} ON {$wpdb->term_taxonomy}.term_taxonomy_id={$wpdb->term_relationships}.term_taxonomy_id
  AND {$wpdb->term_taxonomy}.taxonomy='{$this->taxonomy}'
SQL;
    }
    return $join;
  }
}

Vous appelleriez cette classe comme vous le voyez ci-dessous. L'argument 'taxonomy'est obligatoire mais vous pouvez également passer (tous?) Les autres paramètres WP_Queryattendus, tels que 'posts_per_page':

$query = new PostsByTaxonomy(array(
  'taxonomy' => 'category',
  'posts_per_page' => 25,
));
foreach($query->posts as $post) {
  echo " {$post->post_title}\n";
}

Vous pouvez copier la PostsByTaxonomyclasse dans le functions.phpfichier de votre thème , ou vous pouvez l'utiliser dans un .phpfichier d'un plugin que vous écrivez.

Si vous voulez le tester rapidement, j'ai publié une version autonome du code sur Gist que vous pouvez télécharger et copier à la racine de votre serveur Web en tant que test.php, modifier pour votre cas d'utilisation, puis demander à votre navigateur en utilisant une URL comme http://example.com/test.php.

MISE À JOUR

Pour omettre les messages collants des messages inclus dans la requête, essayez ceci:

$query = new PostsByTaxonomy(array(
  'taxonomy' => 'category',
  'posts_per_page' => 25,
  'caller_get_posts' => true,
));

Ou s'il est important pour vous que la PostsByTaxonomyclasse n'inclue jamais de messages collants, vous pouvez le mettre dans le constructeur:

  function __construct($args=array()) {
    add_filter('posts_join',array(&$this,'posts_join'),10,2);
    $this->posts_by_taxonomy = true;
    $this->taxonomy = $args['taxonomy'];
    $args['caller_get_posts'] = true     // No Sticky Posts
    unset($args['taxonomy']);
    parent::query($args);
  }

MISE À JOUR 2

Après avoir posté ce qui précède, j'ai appris que 'caller_get_posts' sera obsolète et 'ignore_sticky_posts'sera utilisé dans WordPress 3.1.

MikeSchinkel
la source
Mike, merci pour votre aide. Je ne peux pas faire fonctionner cela pour une raison quelconque. Il ne renvoie pas uniquement des messages avec des termes attribués à partir de ma taxonomie personnalisée. Il semble toujours renvoyer d'autres messages. Cependant, il ne retourne pas tous les messages, donc il fait définitivement quelque chose ... Suis-je capable d'utiliser la fonction $ query-> have_posts () pour itérer? Aucune méthode ne semble fonctionner pour moi, de toute façon.
Dave Morris
Ah, c'est intéressant. J'ai trouvé la requête dans le journal mysql qui obtient les deux messages que j'attends, et cela fonctionne. Mais pour une raison quelconque, cinq messages reviennent lorsque je passe en revue les messages $ query->. La seule autre chose que je remarque est que, immédiatement après l'exécution de la requête de publication de taxonomie personnalisée, une autre requête s'exécute qui récupère trois autres publications, par leur post_id. Et puis je suppose que les cinq messages sont placés dans un tableau de résultats.
Dave Morris
Je pense que je l'ai compris. Cette requête personnalisée semble inclure des articles collants, même s'ils ne figurent pas dans cette taxonomie personnalisée. Avez-vous des idées sur la façon d'honorer correctement les messages collants, ou au moins de les retirer de cette requête particulière? Merci, Dave
Dave Morris
Eh bien, ils sont "collants" , non? :) C'est un comportement étrange, je pense, mais si vous utilisez caller_get_posts=1et qu'ils devraient disparaître: codex.wordpress.org/Function_Reference/… J'espère que cela vous aidera.
MikeSchinkel
C'est if(isset($query->posts_by_taxonomy))une bonne astuce pour combiner la méthodologie orientée objet avec la méthodologie de hook de WordPress.
Jan Fabry
1

Vous devez simplement pouvoir définir la taxonomie et annuler pour inclure un terme.

Par exemple.

<?php
$your_query = new WP_query;
$your_query->query( array( 'taxonomy' => 'your-taxonomy-name' ) );
?>

Ce qui serait à peu près la même que la requête effectuée par une archive de taxonomie.

t31os
la source
Ça ne marche pas.
Dave Morris
La ligne 1432 de query.php vérifie si la taxonomie OU le terme sont vides, vous ne pouvez donc pas ne pas passer un slug ... D'autres idées?
Dave Morris
@ t31os - C'était peut-être aussi la première réaction; En fait, j'ai été trébuché plus d'une fois depuis que j'oublie. Mais @Dave Morris a raison; si ce n'est pas une paire taxonomie / terme, jetez WP_Query-la.
MikeSchinkel
6
@ t31os - Yup, WP_Queryn'est malheureusement pas implémenté d'une manière aussi élégante. C'est près de 1200 lignes de cas spéciaux codés en dur.
MikeSchinkel
3
"près de 1200 lignes de cas spéciaux codés en dur." ... qui m'a fait lol, a dû +1 le commentaire ...;)
t31os