Question

J'ai 2 types de poste personnalisé « signets » et « snippets » et une taxonomie commune « tag ». Je peux générer une liste de tous les termes de la taxonomie avec get_terms (), mais je ne peux pas comprendre comment limiter la liste au type poste. Ce que je suis à la recherche essentiellement pour quelque chose comme ceci:

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

Y at-il un moyen d'y parvenir? Les idées sont très appréciés !!

Oh, je suis sur WP 3.1.1

Était-ce utile?

La solution

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;

}

Autres conseils

Alors il arrive juste que je 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 messages d'un type personnalisé, je vérifie quels sont les termes réels de ma taxonomie qu'ils utilisent.

Je suis tous les termes de cette taxonomie à l'aide get_terms() et je ne ai utilisé ceux qui étaient dans les deux listes, l'enveloppa dans une fonction et je fait.

Mais alors je besoin puis juste de l'ID: je avais besoin les noms alors j'ai ajouté un nouvel argument nommé $fields pour que je puisse dire à la fonction que pour revenir. Ensuite, je me suis dit que get_terms accepte de nombreux arguments et ma fonction était simplement limité à des termes qui sont utilisés par un type poste donc j'ajouté une déclaration if et là vous allez:

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 de terme id est alors:

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

Si vous avez seulement besoin d'une liste de noms à terme alors:

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

Si vous objets seulement besoin d'une liste de termes alors:

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

Et si vous avez besoin d'utiliser des arguments supplémentaires de get_terms comme: orderby, l'ordre hiérarchique ...

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

Amusez-vous!

Mise à jour:

Pour fixer le nombre terme au changement spécifique du type de message:

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;
    }
}

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

HT à @braydon pour écrire le 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);

Grandes réponses aux questions et solides.

J'ai vraiment aimé l'approche par @jessica en utilisant le filtre terms_clauses, car elle étend la fonction get_terms d'une 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);

Parce que get_terms ne dispose pas d'une clause de Groupy BY, je devais l'ajouter à la fin de la clause WHERE. Notez que je l'ensemble des priorités de filtre très élevé, dans l'espoir qu'il sera toujours passer en dernier.

je ne pouvais pas faire les arguments de get_terms à travailler avec la version de Gavin du code ci-dessus, mais a finalement fait en changeant

$terms2 = get_terms( $taxonomy );

à

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

comme dans la fonction d'origine de Bainternet.

@Bainternet: Merci! Je devais modifier légèrement la fonction parce qu'il ne fonctionnait pas (quelques fautes de frappe). Le seul problème est maintenant que le compte à terme est éteint. Le nombre ne prend pas le type après en considération, donc je ne pense pas que vous pouvez utiliser get_terms () dans ce domaine.

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 correctif (s). Mais de toute façon il ne fonctionne toujours pas pour moi. Le compteur indique toujours la valeur incorrecte.

éviter 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;
        }
Licencié sous: CC-BY-SA avec attribution
Non affilié à wordpress.stackexchange
scroll top