get_terms nach benutzerdefiniertem Beitragstyp


19

Ich habe zwei benutzerdefinierte Beitragstypen "Land" und "Stadt" und eine gemeinsame Taxonomie "Flagge".

Wenn ich benutze:

<?php $flags = get_terms('flag', 'orderby=name&hide_empty=0');

Ich erhalte eine Liste aller Begriffe in der Taxonomie, möchte die Liste jedoch auf den Beitragstyp "Land" beschränken.

Wie kann ich es tun?


Verwenden der neuen Lösung

<?php 
$flags = wpse57444_get_terms('flags',array('parent' => 0,'hide_empty' => 1,'post_types' =>array('country')));
foreach ($flags as $flag) {
    $childTerms = wpse57444_get_terms('flags',array('parent' => $flag->term_id,'hide_empty' => 1,'post_types' =>array('country')));
    foreach ($childTerms as $childTerm) {
        echo $childTerm->name.'<br />';
    }
}
?>

Ich kann $ childTerm-> name nicht ausgeben. Warum?


Könnten Sie etwas klarer sein?
TheDeadMedic

Antworten:


16

Ich fürchte, das ist von Haus aus (noch?) Nicht möglich. Siehe diesen Trac: http://core.trac.wordpress.org/ticket/18106

In ähnlicher Weise spiegelt die Anzahl der Posts auf der Taxonomie-Administrationsseite alle Post-Typen wider . ( Ich bin mir ziemlich sicher, dass es dafür auch ein Trac-Ticket gibt ) http://core.trac.wordpress.org/ticket/14084

Siehe auch diesen verwandten Beitrag .


Neue Lösung

Nachdem ich den folgenden Artikel geschrieben habe, habe ich einen viel besseren Weg (zumindest in dem Sinne, dass Sie mehr tun können) gefunden, die im get_terms()Aufruf bereitgestellten Filter zu verwenden . Sie können eine Wrapper-Funktion erstellen, die get_termseinen Filter verwendet und (bedingt) hinzufügt, um die SQL-Abfrage zu bearbeiten (um sie nach Post-Typ einzuschränken).

Die Funktion akzeptiert die gleichen Argumente wie get_terms($taxonomies, $args). $argsNimmt das zusätzliche Argument, post_typesdas ein Array von Post-Typen annimmt.

Aber ich kann nicht garantieren, dass alles "wie erwartet" funktioniert (ich denke, die Zählung aufzufüllen). Es scheint nur mit der Standardeinstellung $argsfür zu funktionieren get_terms.

function wpse57444_get_terms( $taxonomies, $args=array() ){
    //Parse $args in case its a query string.
    $args = wp_parse_args($args);

    if( !empty($args['post_types']) ){
        $args['post_types'] = (array) $args['post_types'];
        add_filter( 'terms_clauses','wpse_filter_terms_by_cpt',10,3);

        function wpse_filter_terms_by_cpt( $pieces, $tax, $args){
            global $wpdb;

            // Don't use db count
            $pieces['fields'] .=", COUNT(*) " ;

            //Join extra tables to restrict by post type.
            $pieces['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 ";

            // Restrict by post type and Group by term_id for COUNTing.
            $post_types_str = implode(',',$args['post_types']);
            $pieces['where'].= $wpdb->prepare(" AND p.post_type IN(%s) GROUP BY t.term_id", $post_types_str);

            remove_filter( current_filter(), __FUNCTION__ );
            return $pieces;
        }
    } // endif post_types set

    return get_terms($taxonomies, $args);           
}

Verwendung

$args =array(
    'hide_empty' => 0,
    'post_types' =>array('country','city'),
);

$terms = wpse57444_get_terms('flag',$args);

Ursprüngliche Umgehung

Inspiriert von dem obigen Trac-Ticket (getestet, und es funktioniert bei mir)

function wpse57444_filter_terms_by_cpt($taxonomy, $post_types=array() ){
    global $wpdb;

    $post_types=(array) $post_types;
    $key = 'wpse_terms'.md5($taxonomy.serialize($post_types));
    $results = wp_cache_get($key);

    if ( false === $results ) {
       $where =" WHERE 1=1";
       if( !empty($post_types) ){
            $post_types_str = implode(',',$post_types);
            $where.= $wpdb->prepare(" AND p.post_type IN(%s)", $post_types_str);
       }

       $where .= $wpdb->prepare(" AND tt.taxonomy = %s",$taxonomy);

       $query = "
          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
          GROUP BY t.term_id";

       $results = $wpdb->get_results( $query );
       wp_cache_set( $key, $results );
    }        

    return $results;
}

Verwendung

 $terms = wpse57444_filter_terms_by_cpt('flag',array('country','city'));

oder

 $terms = wpse57444_filter_terms_by_cpt('flag','country');

Es funktioniert, aber was kann ich mit meinen $ args machen? Ich meine ... parent = 0 & orderby = name & hide_empty = 0
user1443216

nein - das muss ein Array sein: $args = array('parent'=>0,'orderby'=>'name','hide_empty'=>0);. Ich werde dies bearbeiten, um Abfragezeichenfolgen zu ermöglichen ...
Stephen Harris

Wo kann ich meine $ args in diesem Beispiel setzen: $terms = wpse57444_filter_terms_by_cpt('flag',array('country','city'));?
user1443216

Sie können nicht in diesem, nur in der neuen Lösung:wpse57444_get_terms()
Stephen Harris

@ user1443216 $argsist das zweite Argument. Dort haben Sie geradewpse57444_get_terms( 'flag', array( 'country', 'city' ) );
Kaiser

2

@ stephen-harris Antwort oben hat nur teilweise bei mir funktioniert. Wenn ich versucht habe, es zweimal auf der Seite zu verwenden, hat es nicht funktioniert. Auch die Idee, solche MySQL-Abfragen zu vergraben, beunruhigt mich. Ich denke, es ist besser, Kernmethoden zu verwenden, um eine Lösung zu finden und Konflikte mit zukünftigen WP-Updates zu vermeiden. Hier ist meine Lösung, basierend auf einem Kommentar # 7 zum Trac-Ticket, auf das er verweist

function get_terms_by_custom_post_type( $post_type, $taxonomy ){
  $args = array( 'post_type' => $post_type);
  $loop = new WP_Query( $args );
  $postids = array();
  // build an array of post IDs
  while ( $loop->have_posts() ) : $loop->the_post();
    array_push($postids, get_the_ID());
  endwhile;
  // get taxonomy values based on array of IDs
  $regions = wp_get_object_terms( $postids,  $taxonomy );
  return $regions;
}

Verwendung:

$terms = get_terms_by_custom_post_type('country','flag');

Dies funktioniert nur für einen Beitragstyp und eine Taxonomie, da ich das benötige, aber es wäre nicht zu schwierig, dies zu ändern, um mehrere Werte zu akzeptieren.

Es wurde auf diesem Trac-Thread erwähnt, dass dies möglicherweise nicht gut skaliert, aber ich arbeite in einem ziemlich kleinen Maßstab und hatte keine Probleme mit der Geschwindigkeit.


Diese Lösung erscheint mir sowieso "nativer" -> Sie sollten "wp_reset_postdata ()" direkt nach dem "endwhile" der Schleife aufrufen: wordpress.stackexchange.com/questions/144343/…
Thomas Fellinger

2

Zwei benutzerdefinierte Beitragstypen "Land" und "Stadt" und eine gemeinsame Taxonomie "Flagge". Sie möchten die Liste auf den Beitragstyp "Land" beschränken.

Hier ist eine einfachere Lösung:

$posts_in_post_type = get_posts( array(
    'fields' => 'ids',
    'post_type' => 'country',
    'posts_per_page' => -1,
) );
$terms = wp_get_object_terms( $posts_in_post_type, 'flag', array( 'ids' ) ); ?>

1

[edit] Dies ist ein Kommentar zu der hervorragenden Antwort von Stephen Harris.

Bei Verwendung mit mehreren Beitragstypen wie diesem werden keine Begriffe zurückgegeben $flags = wpse57444_get_terms('flags', array('post_types' => array('country','city')));. Dies liegt daran, dass $ wpdb-> prepare die Zeichenfolge $ post_types_str so lange bereinigt, wie p.post_type IN('country,city')es sein sollte p.post_type IN('country','city'). Siehe dieses Ticket: 11102 . Verwenden Sie die Lösung aus diesem Thema, um dies zu umgehen : /programming//a/10634225


1

Ich habe auch versucht, die Antwort von @Stephen Harris zu verwenden, aber die Abfrage, die ich benötigte, war als einzelne Abfrage und unter Verwendung der Filterelemente ziemlich schwer zu schreiben.

Darüber hinaus musste ich diese Funktion auch mehrmals auf derselben Seite verwenden und das Problem lösen, bei dem die wpse_filter_terms_by_cptFunktion außerhalb der Wrapper-Funktion deklariert wurde .

Trotzdem passt die Antwort von @Mark Pruce meiner Meinung nach aus den gleichen Gründen besser, wie er sagte, obwohl Sie eine weitere Abfrage (und die zugehörige Schleife) durchführen müssen, um die Argumente für die wp_get_object_termsFunktion vorzubereiten .

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.