Obtenir les termes par taxonomie ET type_poste

16

J'ai 2 types de messages personnalisés, "signets" et "extraits", ainsi qu'une "balise" de taxonomie partagée. Je peux générer une liste de tous les termes de la taxonomie avec get_terms (), mais je ne vois pas comment limiter la liste au type de publication. Ce que je recherche fondamentalement, c'est quelque chose comme ceci:

get_terms(array('taxonomy' => 'tag', 'post_type' => 'snippet'));

Y a-t-il un moyen d'y parvenir? Les idées sont grandement appréciées!

Oh, je suis sur WP 3.1.1

    
posée Gavin Hewitt 09.04.2011 - 02:38
la source

7 réponses

11

Voici une autre façon de faire quelque chose de similaire, avec une requête SQL:

static public function get_terms_by_post_type( $taxonomies, $post_types ) {

    global $wpdb;

    $query = $wpdb->prepare(
        "SELECT t.*, COUNT(*) from $wpdb->terms AS t
        INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id
        INNER JOIN $wpdb->term_relationships AS r ON r.term_taxonomy_id = tt.term_taxonomy_id
        INNER JOIN $wpdb->posts AS p ON p.ID = r.object_id
        WHERE p.post_type IN('%s') AND tt.taxonomy IN('%s')
        GROUP BY t.term_id",
        join( "', '", $post_types ),
        join( "', '", $taxonomies )
    );

    $results = $wpdb->get_results( $query );

    return $results;

}
    
réponse donnée Braydon 26.07.2011 - 10:40
la source
14

Il se trouve donc que j’avais besoin de quelque chose comme ça pour un projet sur lequel je travaille. J'ai simplement écrit une requête pour sélectionner tous les articles d'un type personnalisé, puis je vérifie quels sont les termes réels de ma taxonomie qu'ils utilisent.

Ensuite, j'ai eu tous les termes de cette taxonomie en utilisant get_terms() , puis je n'ai utilisé que ceux qui figuraient dans les deux listes, je l'ai intégré à une fonction et j'ai terminé.

Mais ensuite, il me fallait plus que les identifiants: j'avais besoin des noms, j'ai donc ajouté un nouvel argument nommé $fields afin de pouvoir indiquer à la fonction ce qu'elle doit renvoyer. Ensuite, j’ai pensé que get_terms acceptait de nombreux arguments et que ma fonction était limitée à de simples termes utilisés par un type de publication. J’ajoute une nouvelle déclaration if et voilà:

La fonction:

/* get terms limited to post type 
 @ $taxonomies - (string|array) (required) The taxonomies to retrieve terms from. 
 @ $args  -  (string|array) all Possible Arguments of get_terms http://codex.wordpress.org/Function_Reference/get_terms
 @ $post_type - (string|array) of post types to limit the terms to
 @ $fields - (string) What to return (default all) accepts ID,name,all,get_terms. 
 if you want to use get_terms arguments then $fields must be set to 'get_terms'
*/
function get_terms_by_post_type($taxonomies,$args,$post_type,$fields = 'all'){
    $args = array(
        'post_type' => (array)$post_type,
        'posts_per_page' => -1
    );
    $the_query = new WP_Query( $args );
    $terms = array();
    while ($the_query->have_posts()){
        $the_query->the_post();
        $curent_terms = wp_get_object_terms( $post->ID, $taxonomy);
        foreach ($curent_terms as $t){
          //avoid duplicates
            if (!in_array($t,$terms)){
                $terms[] = $c;
            }
        }
    }
    wp_reset_query();
    //return array of term objects
    if ($fields == "all")
        return $terms;
    //return array of term ID's
    if ($fields == "ID"){
        foreach ($terms as $t){
            $re[] = $t->term_id;
        }
        return $re;
    }
    //return array of term names
    if ($fields == "name"){
        foreach ($terms as $t){
            $re[] = $t->name;
        }
        return $re;
    }
    // get terms with get_terms arguments
    if ($fields == "get_terms"){
        $terms2 = get_terms( $taxonomies, $args );
        foreach ($terms as $t){
            if (in_array($t,$terms2)){
                $re[] = $t;
            }
        }
        return $re;
    }
}

Utilisation:

Si vous avez seulement besoin d'une liste d'identifiants de termes, alors:

$terms = get_terms_by_post_type('tag','','snippet','ID');

Si vous n'avez besoin que d'une liste de noms de termes, alors:

$terms = get_terms_by_post_type('tag','','snippet','name');

Si vous n’avez besoin que d’une liste d’objets termes, alors:

$terms = get_terms_by_post_type('tag','','snippet');

Et si vous devez utiliser des arguments supplémentaires de get_terms tels que: orderby, order, hierarchical ...

$args = array('orderby' => 'count', 'order' => 'DESC',  'hide_empty' => 1);
$terms = get_terms_by_post_type('tag',$args,'snippet','get_terms');

Profitez!

Mise à jour:

Pour définir le nombre de termes associés à un changement de type de message spécifique:

foreach ($current_terms as $t){
          //avoid duplicates
            if (!in_array($t,$terms)){
                $terms[] = $t;
            }
        }

à:

foreach ($current_terms as $t){
    //avoid duplicates
    if (!in_array($t,$terms)){
        $t->count = 1;
        $terms[] = $t;
    }else{
        $key = array_search($t, $terms);
        $terms[$key]->count = $terms[$key]->count + 1;
    }
}
    
réponse donnée Bainternet 09.04.2011 - 03:21
la source
8

J'ai écrit une fonction qui vous permet de passer post_type du tableau $args à la fonction get_terms() :

HT à @braydon pour l'écriture du code SQL.

 /**
 * terms_clauses
 *
 * filter the terms clauses
 *
 * @param $clauses array
 * @param $taxonomy string
 * @param $args array
 * @return array
**/
function terms_clauses($clauses, $taxonomy, $args)
{
    global $wpdb;

    if ($args['post_type'])
    {
        $clauses['join'] .= " INNER JOIN $wpdb->term_relationships AS r ON r.term_taxonomy_id = tt.term_taxonomy_id INNER JOIN $wpdb->posts AS p ON p.ID = r.object_id";
        $clauses['where'] .= " AND p.post_type='{$args['post_type']}'"; 
    }
    return $clauses;
}
add_filter('terms_clauses', 'terms_clauses', 10, 3);
    
réponse donnée jessica 08.06.2012 - 07:14
la source
7

Excellente question et réponses solides.

J'ai vraiment aimé l'approche de @ jessica utilisant le filtre terms_clauses, car elle étend la fonction get_terms de manière très raisonnable.

Mon code est une continuation de son idée, avec quelques SQL de @braydon pour réduire les doublons. Il permet également un tableau de post_types:

/**
 * my_terms_clauses
 *
 * filter the terms clauses
 *
 * @param $clauses array
 * @param $taxonomy string
 * @param $args array
 * @return array
 **/
function my_terms_clauses($clauses, $taxonomy, $args)
{
  global $wpdb;

  if ($args['post_types'])
  {
    $post_types = $args['post_types'];

    // allow for arrays
    if ( is_array($args['post_types']) ) {
      $post_types = implode("','", $args['post_types']);
    }
    $clauses['join'] .= " INNER JOIN $wpdb->term_relationships AS r ON r.term_taxonomy_id = tt.term_taxonomy_id INNER JOIN $wpdb->posts AS p ON p.ID = r.object_id";
    $clauses['where'] .= " AND p.post_type IN ('". esc_sql( $post_types ). "') GROUP BY t.term_id";
  }
  return $clauses;
}
add_filter('terms_clauses', 'my_terms_clauses', 99999, 3);

Comme get_terms n’a pas de clause pour GROUPY BY, je devais l’ajouter à la fin de la clause WHERE. Notez que la priorité du filtre est très haute, dans l’espoir que cela restera toujours le dernier.

    
réponse donnée daggerhart 04.04.2015 - 05:09
la source
3

Je ne pouvais pas utiliser les arguments get_terms pour fonctionner avec la version de Gavin du code ci-dessus, mais je l'ai finalement fait en modifiant

.
$terms2 = get_terms( $taxonomy );

à

$terms2 = get_terms( $taxonomy, $args );

comme dans la fonction d'origine de Bainternet.

    
réponse donnée tzeldin88 10.04.2011 - 04:16
la source
0

@Bainternet: Merci! J'ai dû modifier légèrement la fonction car cela ne fonctionnait pas (quelques fautes de frappe). Le seul problème est que le compte est désactivé. Le nombre ne prend pas en compte le type de publication, je ne pense donc pas que vous puissiez utiliser get_terms () pour cela.

function get_terms_by_post_type($post_type,$taxonomy,$fields='all',$args){
    $q_args = array(
        'post_type' => (array)$post_type,
        'posts_per_page' => -1
    );
    $the_query = new WP_Query( $q_args );

    $terms = array();

    while ($the_query->have_posts()) { $the_query->the_post();

        global $post;

        $current_terms = get_the_terms( $post->ID, $taxonomy);

        foreach ($current_terms as $t){
            //avoid duplicates
            if (!in_array($t,$terms)){
                $t->count = 1;
                $terms[] = $t;
            }else{
                $key = array_search($t, $terms);
                $terms[$key]->count = $terms[$key]->count + 1;
            }
        }
    }
    wp_reset_query();

    //return array of term objects
    if ($fields == "all")
        return $terms;
    //return array of term ID's
    if ($fields == "ID"){
        foreach ($terms as $t){
            $re[] = $t->term_id;
        }
        return $re;
    }
    //return array of term names
    if ($fields == "name"){
        foreach ($terms as $t){
            $re[] = $t->name;
        }
        return $re;
    }
    // get terms with get_terms arguments
    if ($fields == "get_terms"){
        $terms2 = get_terms( $taxonomy, $args );

        foreach ($terms as $t){
            if (in_array($t,$terms2)){
                $re[] = $t;
            }
        }
        return $re;
    }
}

EDIT: Ajout du ou des correctifs. Mais de toute façon, cela ne fonctionne toujours pas pour moi. Le nombre affiche toujours la valeur incorrecte.

    
réponse donnée Gavin Hewitt 09.04.2011 - 13:45
la source
0

Évitez les doublons:

//avoid duplicates
    $mivalor=$t->term_id;
    $arr=array_filter($terms, function ($item) use ($mivalor) {return isset($item->term_id) && $item->term_id == $mivalor;});

    if (empty($arr)){
    $t->count=1;
            $terms[] = $t;
        }else{
            $key = array_search($t, $terms);
            $terms[$key]->count = $terms[$key]->count + 1;
        }
    
réponse donnée Kaotiko 26.02.2013 - 18:10
la source

Lire d'autres questions sur les étiquettes