web-dev-qa-db-fra.com

Taxonomie personnalisée, get_the_terms, liste par ordre de parent> enfant

J'ai une taxonomie personnalisée hiérarchique que je peux afficher à l'aide de print_r(get_the_terms( $post->ID, 'taxonomic_rank' ));:

Array
(
    [46] => stdClass Object
        (
            [term_id] => 46
            [name] => Aplocheilidae
            [slug] => aplocheilidae
            [term_group] => 0
            [term_taxonomy_id] => 53
            [taxonomy] => taxonomic_ranks
            [description] => 
            [parent] => 39
            [count] => 1
            [object_id] => 443
        )

    [47] => stdClass Object
        (
            [term_id] => 47
            [name] => Aplocheilus
            [slug] => aplocheilus
            [term_group] => 0
            [term_taxonomy_id] => 54
            [taxonomy] => taxonomic_ranks
            [description] => 
            [parent] => 46
            [count] => 1
            [object_id] => 443
        )

    [39] => stdClass Object
        (
            [term_id] => 39
            [name] => Cyprinodontiformes
            [slug] => cyprinodontiformes
            [term_group] => 0
            [term_taxonomy_id] => 52
            [taxonomy] => taxonomic_ranks
            [description] => 
            [parent] => 0
            [count] => 1
            [object_id] => 443
        )

)

Cette taxonomie prendra toujours la forme suivante: Ordre (parent)> Famille (enfant de l’ordre)> Sous-famille (enfant de famille)

Existe-t-il un moyen simple et rapide d'afficher ces taxonomies dans le bon ordre, afin que je puisse imprimer la ligne suivante? Order: <order>, Family: <family>, Sub-family: <sub-family>

Merci d'avance

6
dunc

Il existe probablement de meilleures façons de procéder, mais vous pouvez toujours créer trois boucles foreach simples.

J'ai écrit un exemple de fonction qui fait bien le travail et devrait vous servir de bon point de départ:

function print_taxonomic_ranks( $terms = '' ){

    // check input
    if ( empty( $terms ) || is_wp_error( $terms ) || ! is_array( $terms ) )
        return;

    // set id variables to 0 for easy check 
    $order_id = $family_id = $subfamily_id = 0;

    // get order
    foreach ( $terms as $term ) {
        if ( $order_id || $term->parent )
            continue;
        $order_id  = $term->term_id;
        $order     = $term->name;
    }

    // get family
    foreach ( $terms as $term ) { 
        if ( $family_id || $order_id != $term->parent )
            continue;
        $family_id = $term->term_id;
        $family    = $term->name;
    }

    // get subfamily
    foreach ( $terms as $term ) { 
        if ( $subfamily_id || $family_id != $term->parent ) 
            continue;
        $subfamily_id = $term->term_id;
        $subfamily    = $term->name;
    }

    // output
    echo "Order: $order, Family: $family, Sub-family: $subfamily";

}

Laissez-le vivre dans votre fichier functions.php et utilisez-le dans vos modèles comme ceci:

print_taxonomy_ranks( get_the_terms( $post->ID, 'taxonomic_rank' ) );

NOTE: Boucler la même matrice trois fois semble un peu stupide, mais en revanche c'est une solution rapide et facile qui est facile à lire, à étendre et à maintenir.

6
Michal Mau

Bien que l'approche de Maugly semble un peu plus lisible, faire tourner une boucle trois fois sur le tableau ne me semble pas correct. Donc, voici juste une autre approche qui pourrait être moins lisible pour certains, mais fonctionne sans exécuter la boucle 3 fois.

function print_taxonomy_ranks( $terms ) {
    // if terms is not array or its empty don't proceed
    if ( ! is_array( $terms ) || empty( $terms ) ) {
        return false;
    }

    foreach ( $terms as $term ) {
        // if the term have a parent, set the child term as attribute in parent term
        if ( $term->parent != 0 )  {
            $terms[$term->parent]->child = $term;   
        } else {
            // record the parent term
            $parent = $term;
        }
    }

    echo "Order: $parent->name, Family: {$parent->child->name}, Sub-Family: {$parent->child->child->name}";
}
4
Hameedullah Khan

Un sujet un peu vieux mais toujours d'actualité, je pense, car c'est toujours une douleur complète.

J'utilise cette fonction récursive qui prend deux tableaux comme références. Cela créera un tableau avec la structure suivante: [term_id] => term_object->children->child_terms_array->children->child_terms_array.

<?php
function sort_terms_hierarchically( array &$terms, array &$into, $parent_id = 0 ) {
    foreach ( $terms as $i => $term ) {
        if ( $term->parent == $parent_id ) {
            $into[$term->term_id] = $term;
            unset( $terms[ $i ] );
        }
    }

    foreach ( $into as $top_term ) {
        $top_term->children = array();
        $this->sort_terms_hierarchically( $terms, $top_term->children, $top_term->term_id );
    }

}

$terms = get_the_terms( 'taxslug', $post );
$sorted_terms = array();
sort_terms_hierarchically( $terms, $sorted_terms );

// Will log the nested arrays of term objects.
error_log( print_r( $sorted_terms, true ) );

C'est la seule solution que j'ai jamais trouvée qui maintienne le terme objets et fonctionne avec n'importe quelle quantité d'imbrication.

3
Jonathan de Jong

Dans certains cas, une publication pouvait être étiquetée avec plusieurs groupes de catégories et plusieurs enfants au sein de catégories de parents. Je voulais donc que ma hiérarchie reflète cela. Je voulais aussi juste quelques lignes de code:

$terms = get_the_terms($id, 'department_categories');
foreach($terms as $key => $term){
    if($term->parent != 0){
        $terms[$term->parent]->children[] = $term;
        unset($terms[$key]);
    }
}

En gros, après avoir trouvé le parent d'une catégorie, il la déplace dans l'objet obj du parent, puis la supprime de sa position d'origine dans le tableau. J'ai testé cela en utilisant plusieurs frères et sœurs, enfants et différents niveaux de catégories.

J'espère que quelqu'un trouvera cela utile au cas où ils chercheraient simplement un guide logique plutôt qu'un "plugin"!

3
Kaitlyn McDonald

Merci Maugly,

Voici ma version modifiée de votre code qui inclut le terme permaliens si quelqu'un en a besoin

function print_show_location( $terms = '' ){

// check input
if ( empty( $terms ) || is_wp_error( $terms ) || ! is_array( $terms ) )
    return;

// set id variables to 0 for easy check 
$country_id = $state_id = $city_id = 0;

// get country
foreach ( $terms as $term ) {
    if ( $country_id || $term->parent )
        continue;
    $country_id  = $term->term_id;
    $country_slug = $term->slug;
    $country = '<a href="'.get_term_link($country_slug, 'location').'">'.$term->name.'</a>';
}

// get state
foreach ( $terms as $term ) { 
    if ( $state_id || $country_id != $term->parent )
        continue;
    $state_id = $term->term_id;
    $state_slug = $term->slug;
    $state = '<a href="'.get_term_link($state_slug, 'location').'">'.$term->name.'</a>';
}

// get city
foreach ( $terms as $term ) { 
    if ( $city_id || $state_id != $term->parent ) 
        continue;
    $city_id = $term->term_id;
    $city_slug = $term->slug;
    $city = '<a href="'.get_term_link($city_slug, 'location').'">'.$term->name.'</a>';
}

// output
echo "$city, $state - $country";

}
1
Adam Forst