web-dev-qa-db-fra.com

Combinez deux taxonomies dans un arbre hiérarchique

Par exemple, j'ai des produits WooCommerce qui ont des taxonomies:

  • marque (par exemple, Converse, adidas, D & G) (id de taxonomie: product_brand)
  • catégorie (par exemple, bottes, baskets, sandales, talons) (id de taxonomie: product_cat)

Bien sûr, toutes les marques ne comprennent pas toutes les catégories.

Je dois lister les catégories par marque. (quelque chose de similaire à ce que Zappos fait . E.g .:

Converse
- Sandals (2)
- Sneakers (6)

D&G
- Boots (10)
- Heels (4)
- Sandals (7)

Y a-t-il un moyen léger de le faire, sauf de parcourir tous les produits avec une marque spécifique et de vérifier leur catégorie?

5
Marvin3

Pour obtenir une liste de tous les termes de la taxonomie X dont les messages sont associés à des termes de la taxonomie Y également, nous devons:

  1. Obtenez tous les identifiants de terme pour les deux taxonomies
  2. Créez une requête fiscale pour récupérer tous les articles, car nous ne voulons pas afficher d'archives de termes vides.
  3. Formatez le résultat dans une liste hiérarchique.

Allons-y!

  1. Obtenir les identifiants de terme est simple:

    get_terms( $taxonomy_name, array( 'fields' => 'ids' ) )
    

    Nous devons juste le faire deux fois (pour chaque taxonomie une fois).

  2. La requête de taxonomie nécessite une relation AND pour s'assurer que tous les messages que nous recevons sont / dans les deux taxonomies:

        'tax_query'        => array (
            'relation' => 'AND',
            array(
                'taxonomy' => $first,
                'field'    => 'id',
                'terms'    => get_terms( $first, array( 'fields' => 'ids' ) )
            ),
            array(
                'taxonomy' => $second,
                'field'    => 'id',
                'terms'    => get_terms( $second, array( 'fields' => 'ids' ) )
            ),
        ),
    
  3. Pour la mise en forme, nous créons un tableau où les termes de la première taxonomie sont les clés et les termes de la seconde taxonomie sont les valeurs. Ensuite, nous construisons une liste imbriquée avec des éléments simples <ul>.

Maintenant, la fonction: j'ai utilisé les balises et les catégories comme taxonomies, simplement parce que c'était plus facile à tester.

function double_term_tree(
    $post_types = array( 'post', 'page' ),
    $first      = 'category',
    $second     = 'post_tag'
    )
{
    $query = new WP_Query(
        array (
            'numberposts'      => -1,
            'suppress_filters' => TRUE,
            'posts_per_page'   => -1,
            'post_type'        => $post_types,
            'tax_query'        => array (
                'relation' => 'AND',
                array(
                    'taxonomy' => $first,
                    'field'    => 'id',
                    'terms'    => get_terms( $first, array( 'fields' => 'ids' ) )
                ),
                array(
                    'taxonomy' => $second,
                    'field'    => 'id',
                    'terms'    => get_terms( $second, array( 'fields' => 'ids' ) )
                ),
            ),
        )
    );

    if ( empty ( $query->posts ) )
        return;

    $result_list = array();
    $output      = '<ul>';

    foreach ( $query->posts as $post )
    {
        $first_terms  = get_the_term_list( $post->ID, $first, '', '|' );
        $second_terms = get_the_term_list( $post->ID, $second, '', '|' );

        $f_term_array = explode( '|', $first_terms );
        $s_term_array = explode( '|', $second_terms );

        foreach ( $f_term_array as $f_term )
        {
            if ( ! isset ( $result_list[ $f_term ] ) )
                $result_list[ $f_term ] = array();

            $result_list[ $f_term ] = array_merge( $result_list[ $f_term ], $s_term_array );
        }
    }

    foreach ( $result_list as $k => $v )
    {
        $result_list[ $k ] = array_unique( $v );
        $output           .= "\n<li>$k\n\t<ul>\n\t\t<li>"
            . join( "</li>\n\t\t<li>", array_unique( $v ) )
            . "</li>\n\t</ul>\n</li>";
    }

    $output .= '</ul>';

    return $output;
}

Vous pouvez appeler cette fonction comme ceci:

echo double_term_tree( 'product', 'brand', 'category' );

Et puis vous obtenez cet arbre.

8
fuxia