Wie zeige ich eine hierarchische Begriffsliste an?


34

Ich habe eine hierarchische Taxonomie namens "geografische Standorte". Es enthält Kontinente auf einer ersten Ebene und dann die Länder für jeden einzelnen. Beispiel

Europe
- Ireland
- Spain
- Sweden
Asia
- Laos
- Thailand
- Vietnam

etc.

Mit get_terms () habe ich es geschafft, die vollständige Liste der Begriffe auszugeben, aber die Kontinente werden mit den Ländern in einer großen, flachen Liste verwechselt.

Wie kann ich eine hierarchische Liste wie oben ausgeben?


2
Für den Fall, dass jemand eine hierarchische CHECKLISTE benötigt (nicht die Frage hier, sondern für Benutzer, die eine benutzerdefinierte Benutzeroberfläche für hierarchische Taxonomien erstellen), ist die beste Antwort die Verwendung von wp_terms_checklist () mit Ihrer benutzerdefinierten Taxonomie.
Jerclarke

Antworten:


19

In Verbindung wp_list_categoriesmit dem 'taxonomy' => 'taxonomy'Argument können hierarchische Kategorielisten erstellt werden, es wird jedoch auch die Verwendung einer benutzerdefinierten Taxonomie unterstützt.

Codex-Beispiel:
Anzeigen von Begriffen in einer benutzerdefinierten Taxonomie

Wenn die Liste flach angezeigt wird, ist es möglich, dass Sie nur ein wenig CSS benötigen, um die Listen aufzufüllen, damit Sie ihre hierarchische Struktur sehen können.


Könnte dies umgekehrt werden? Kinder zuerst anzeigen ..
Arg Geo

43

Mir ist klar, dass dies eine sehr alte Frage ist, aber wenn Sie eine tatsächliche Struktur von Begriffen aufbauen müssen, kann dies eine nützliche Methode für Sie sein:

/**
 * Recursively sort an array of taxonomy terms hierarchically. Child categories will be
 * placed under a 'children' member of their parent term.
 * @param Array   $cats     taxonomy term objects to sort
 * @param Array   $into     result array to put them in
 * @param integer $parentId the current parent ID to put them in
 */
function sort_terms_hierarchically(Array &$cats, Array &$into, $parentId = 0)
{
    foreach ($cats as $i => $cat) {
        if ($cat->parent == $parentId) {
            $into[$cat->term_id] = $cat;
            unset($cats[$i]);
        }
    }

    foreach ($into as $topCat) {
        $topCat->children = array();
        sort_terms_hierarchically($cats, $topCat->children, $topCat->term_id);
    }
}

Verwendung ist wie folgt:

$categories = get_terms('my_taxonomy_name', array('hide_empty' => false));
$categoryHierarchy = array();
sort_terms_hierarchically($categories, $categoryHierarchy);

var_dump($categoryHierarchy);

3
Das ist eigentlich ganz gut. Ich würde eine Sache ändern: $into[$cat->term_id] = $cat;in $into[] = $cat;der ID des Begriffs, wie der Array - Schlüssel ärgerlich ist (man kann nicht das erste Element erhält leicht die 0 - Taste) und nutzlos (Sie bereits das Speichern von $catObjekt und Sie können die ID erhalten Nutzung des term_idGrundstücks
Nahuel

Wenn Sie wie ich versuchen, diese Funktion auf eine Unterebene von Kategorien anzuwenden, müssen Sie die ID der Ebene eingeben, auf der Sie sich gerade befinden, damit dies funktioniert. Aber es funktioniert gut, danke @popsi.
Ben Everard

das funktioniert, danke
Luca Reghellin

10

Ich kenne keine Funktion, die das tut, was Sie wollen, aber Sie können so etwas aufbauen:

<ul>
    <?php $hiterms = get_terms("my_tax", array("orderby" => "slug", "parent" => 0)); ?>
    <?php foreach($hiterms as $key => $hiterm) : ?>
        <li>
            <?php echo $hiterm->name; ?>
            <?php $loterms = get_terms("my_tax", array("orderby" => "slug", "parent" => $hiterm->term_id)); ?>
            <?php if($loterms) : ?>
                <ul>
                    <?php foreach($loterms as $key => $loterm) : ?>
                        <li><?php echo $loterm->name; ?></li>
                    <?php endforeach; ?>
                </ul>
            <?php endif; ?>
        </li>
    <?php endforeach; ?>
</ul>

Ich habe das nicht getestet, aber Sie können sehen, worauf ich hinaus will. Mit dem obigen Code erhalten Sie nur zwei Ebenen

EDIT: ahh ja du kannst mit wp_list_categories () machen was du willst.


Tatsächlich ist dies sehr nützlich, da ich benutzerdefinierte Links (mit einem GET-Parameter) für den Begriff "Links" benötigen muss, was mit der Methode "wp_list_categories ()" nicht möglich zu sein scheint.
mike23

1
Ja, diese Methode gibt Ihnen mehr Kontrolle über Ihre Ausgabe. Aber Sie könnten ein bisschen suchen und ersetzen wp_list_categories(), um Ihre GET-Parameter hinzuzufügen. Oder erstellen Sie besser einen Filter für die Funktion, um die gewünschten Bits hinzuzufügen. Fragen Sie mich nicht, wie Sie das machen, da ich es noch nicht verstanden habe :(
Brady

3
Ich würde vorschlagen, einen benutzerdefinierten Kategoriewanderer zu verwenden, mit dem wp_list_categoriesSie die Ausgabe besser
steuern können

6

Sie können wp_list_categories () mit dem Argument 'taxonomy' verwenden.


3

Da ich das selbe aber suchte, um Konditionen für einen Beitrag zu bekommen, habe ich dies endlich kompiliert und es funktioniert bei mir.

Was es tut:
• Es werden alle Begriffe eines Taxonomienamens für einen bestimmten Beitrag abgerufen.
• Für eine hierarchische Taxonomie mit zwei Ebenen (z. B. Ebene 1: 'Land' und Ebene 2: 'Städte') wird ein h4 mit Ebene 1 erstellt, gefolgt von einer ul-Liste von Ebene 2 und dies für alle Elemente der Ebene 1.
• Wenn die Taxonomie nicht hierarchisch ist, wird nur eine ul-Liste aller Elemente erstellt. Hier ist der Code (ich schreibe ihn für mich, also habe ich versucht, so allgemein wie möglich zu sein, aber ...):

function finishingLister($heTerm){
    $myterm = $heTerm;
    $terms = get_the_terms($post->ID,$myterm);
    if($terms){
        $count = count($terms);
        echo '<h3>'.$myterm;
        echo ((($count>1)&&(!endswith($myterm, 's')))?'s':"").'</h3>';
        echo '<div class="'.$myterm.'Wrapper">';
        foreach ($terms as $term) {
            if (0 == $term->parent) $parentsItems[] = $term;
            if ($term->parent) $childItems[] = $term; 
        };
        if(is_taxonomy_hierarchical( $heTerm )){
            foreach ($parentsItems as $parentsItem){
                echo '<h4>'.$parentsItem->name.'</h4>';
                echo '<ul>';
                foreach($childItems as $childItem){
                    if ($childItem->parent == $parentsItem->term_id){
                        echo '<li>'.$childItem->name.'</li>';
                    };
                };
                echo '</ul>';
            };
        }else{
            echo '<ul>';
            foreach($parentsItems as $parentsItem){
                echo '<li>'.$parentsItem->name.'</li>';
            };
            echo '</ul>';
        };
        echo '</div>';
    };
};

Zum Schluss rufen Sie die Funktion mit diesem Befehl auf (offensichtlich ersetzen Sie my_taxonomy durch yours): finishingLister('my_taxonomy');

Ich tue nicht so, als wäre es perfekt, aber wie gesagt, es funktioniert für mich.


3

Der folgende Code generiert ein Dropdown-Menü mit Begriffen, kann aber auch jedes andere Element / jede andere Struktur generieren, indem Sie die Variable $ outputTemplate bearbeiten und die Zeilen str_replace bearbeiten:

function get_terms_hierarchical($terms, $output = '', $parent_id = 0, $level = 0) {
    //Out Template
    $outputTemplate = '<option value="%ID%">%PADDING%%NAME%</option>';

    foreach ($terms as $term) {
        if ($parent_id == $term->parent) {
            //Replacing the template variables
            $itemOutput = str_replace('%ID%', $term->term_id, $outputTemplate);
            $itemOutput = str_replace('%PADDING%', str_pad('', $level*12, '&nbsp;&nbsp;'), $itemOutput);
            $itemOutput = str_replace('%NAME%', $term->name, $itemOutput);

            $output .= $itemOutput;
            $output = get_terms_hierarchical($terms, $output, $term->term_id, $level + 1);
        }
    }
    return $output;
}

$terms = get_terms('taxonomy', array('hide_empty' => false));
$output = get_terms_hierarchical($terms);

echo '<select>' . $output . '</select>';  

1

Ich hatte dieses Problem und keine der Antworten hier hat aus dem einen oder anderen Grund für mich funktioniert.

Hier ist meine aktualisierte und funktionierende Version.

function locationSelector( $fieldName ) {
    $args = array('hide_empty' => false, 'hierarchical' => true, 'parent' => 0); 
    $terms = get_terms("locations", $args);

    $html = '';
    $html .= '<select name="' . $fieldName . '"' . 'class="chosen-select ' . $fieldName . '"' . '>';
        foreach ( $terms as $term ) {
            $html .= '<option value="' . $term->term_id . '">' . $term->name . '</option>';

            $args = array(
                'hide_empty'    => false, 
                'hierarchical'  => true, 
                'parent'        => $term->term_id
            ); 
            $childterms = get_terms("locations", $args);

            foreach ( $childterms as $childterm ) {
                $html .= '<option value="' . $childterm->term_id . '">' . $term->name . ' > ' . $childterm->name . '</option>';

                $args = array('hide_empty' => false, 'hierarchical'  => true, 'parent' => $childterm->term_id); 
                $granchildterms = get_terms("locations", $args);

                foreach ( $granchildterms as $granchild ) {
                    $html .= '<option value="' . $granchild->term_id . '">' . $term->name . ' > ' . $childterm->name . ' > ' . $granchild->name . '</option>';
                }
            }
        }
    $html .=  "</select>";

    return $html;
}

Und Nutzung:

$selector = locationSelector('locationSelectClass');
echo $selector;

1

Ich habe @popsi-Code verwendet, der sehr gut funktioniert hat und der effizienter und einfacher zu lesen ist:

/**
 * Recursively sort an array of taxonomy terms hierarchically. Child categories will be
 * placed under a 'children' member of their parent term.
 * @param Array   $cats     taxonomy term objects to sort
 * @param integer $parentId the current parent ID to put them in
 */
function sort_terms_hierarchicaly(Array $cats, $parentId = 0)
{
    $into = [];
    foreach ($cats as $i => $cat) {
        if ($cat->parent == $parentId) {
            $cat->children = sort_terms_hierarchicaly($cats, $cat->term_id);
            $into[$cat->term_id] = $cat;
        }
    }
    return $into;
}

Verwendung :

$sorted_terms = sort_terms_hierarchicaly($terms);

-1

Sei sicher, dass hierarchical=true an Ihren get_terms()Anruf weitergeleitet wird.

Beachten Sie, dass dies hierarchical=truedie Standardeinstellung ist. Stellen Sie also sicher, dass sie nicht überschrieben wurde false.


Hallo Chip, ja 'hierarchisch' ist standardmäßig 'wahr'.
mike23

Können Sie einen Link zu einem Live-Beispiel der Ausgabe bereitstellen?
Chip Bennett

Eine Antwort kommentieren, die vor fast zwei Jahren noch offen war? "Ja wirklich?" Eigentlich ist es ist eine vorgeschlagene Antwort, auch wenn als Frage formuliert. Soll ich es so bearbeiten, dass es eher eine Aussage als eine Frage ist?
Chip Bennett

get_terms()gibt eine vollständige Liste der Begriffe zurück (wie im OP angegeben), jedoch keine hierarchische Liste, die die angeforderte Eltern-Kind-Beziehung anzeigt.
jdm2112

-1

Hier habe ich eine Dropdown-Auswahlliste mit vier Ebenen und verstecktem ersten Element

<select name="lokalizacja" id="ucz">
            <option value="">Wszystkie lokalizacje</option>
            <?php
            $excluded_term = get_term_by('slug', 'podroze', 'my_travels_places');
            $args = array(
                'orderby' => 'slug',
                'hierarchical' => 'true',
                'exclude' => $excluded_term->term_id,
                'hide_empty' => '0',
                'parent' => $excluded_term->term_id,
            );              
            $hiterms = get_terms("my_travels_places", $args);
            foreach ($hiterms AS $hiterm) :
                echo "<option value='".$hiterm->slug."'".($_POST['my_travels_places'] == $hiterm->slug ? ' selected="selected"' : '').">".$hiterm->name."</option>\n";

                $loterms = get_terms("my_travels_places", array("orderby" => "slug", "parent" => $hiterm->term_id,'hide_empty' => '0',));
                if($loterms) :
                    foreach($loterms as $key => $loterm) :

                    echo "<option value='".$loterm->slug."'".($_POST['my_travels_places'] == $loterm->slug ? ' selected="selected"' : '').">&nbsp;-&nbsp;".$loterm->name."</option>\n";

                    $lo2terms = get_terms("my_travels_places", array("orderby" => "slug", "parent" => $loterm->term_id,'hide_empty' => '0',));
                    if($lo2terms) :
                        foreach($lo2terms as $key => $lo2term) :

                        echo "<option value='".$lo2term->slug."'".($_POST['my_travels_places'] == $lo2term->slug ? ' selected="selected"' : '').">&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;".$lo2term->name."</option>\n";



                        endforeach;
                    endif;

                    endforeach;
                endif;

            endforeach;
            ?>
         </select>
        <label>Wybierz rodzaj miejsca</label>
        <select name="rodzaj_miejsca" id="woj">
            <option value="">Wszystkie rodzaje</option>
            <?php
            $theterms = get_terms('my_travels_places_type', 'orderby=name');
            foreach ($theterms AS $term) :
                echo "<option value='".$term->slug."'".($_POST['my_travels_places_type'] == $term->slug ? ' selected="selected"' : '').">".$term->name."</option>\n";                   
            endforeach;
            ?>
         </select>

2
Bitte erläutern Sie, warum dies das Problem lösen könnte.
fuxia

Ich denke, die Logik ist, dass es ein verwandtes Problem ist. Ich habe diesen Beitrag gefunden, um herauszufinden, wie man eine hierarchische Checkliste im Kategoriestil erhält, und bin versucht, hier eine Antwort hinzuzufügen, nachdem ich es herausgefunden habe. Ich werde es aber nicht tun, weil es, wie Sie darauf hinweisen, die OQ nicht beantwortet.
Jerclarke
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.