web-dev-qa-db-fra.com

Afficher certains termes de la taxonomie personnalisée, mais exclure les termes "parents"?

J'ai un type de message personnalisé "mycustom_products" (hiérarchique) qui a des taxonomies personnalisées appelées "catégories" et "balises" (comme beaucoup d'autres types de messages personnalisés). Ma catégorie personnalisée s'appelle "myprod_category" (également hiérarchique) et ma taxonomie de balise s'appelle "product_tag" ( et non hiérarchique).

Je souhaite afficher une liste de balises de produit correspondant UNIQUEMENT à certaines catégories de produit.

Par exemple, avec des catégories de produits telles que "savon" et "lotion", il peut y avoir des étiquettes appelées "Blueberry" ou "Lavender" (senteurs) mais "bijoux" aurait des étiquettes comme "argent" ou "or". Je veux pouvoir avoir une liste des balises "parfum" uniquement (qui correspondent à celles qui correspondent uniquement aux catégories "savon" et "lotion". Je ne souhaite pas que les balises de "bijoux" soient incluses) Ainsi, toutes les étiquettes qui ont été utilisées sur des produits entrés dans ces catégories seraient incluses, pas plus que celles utilisées pour d’autres catégories.

Évidemment, je pourrais tout coder dans le thème, mais si/lorsque le client ajoute plus de balises, je devrais entrer et tout coder à nouveau et j'aimerais éviter de le faire.

J'ai essayé d'utiliser <?php wp_tag_cloud( array( 'taxonomy' => 'product_tag', format => 'list' ) ); ?> pour répertorier toutes mes balises, mais je n'arrive pas à obtenir l'argument EXCLUDE pour empêcher l'affichage de "catégories de produits" entières. On dirait que je peux le faire en utilisant tag_ID, mais ce serait fastidieux et me ramènerait au codage en dur dans le thème et à la mise à jour à chaque fois qu'une nouvelle balise est ajoutée.

Existe-t-il un filtre ou quelque chose que je peux utiliser pour exclure une catégorie? Ou existe-t-il un meilleur moyen de lister les tags de cette manière? Merci!

2
RodeoRamsey

Si vous avez beaucoup de produits, une requête SQL personnalisée est probablement une meilleure option.

Je recommanderais probablement de suivre cette voie de toute façon. Les requêtes personnalisées sont peut-être "fastidieuses", mais cela allégera les ressources et sera un peu plus rapide dans la plupart des cas *

J'ai écrit une fonction qui représente la majeure partie du travail et qui pourrait s'avérer utile dans d'autres scénarios (j'ai utilisé le mot "soft" pour sous-entendre que les relations ne sont pas explicites).

/**
 * Get terms that are indirectly associated with others through the posts they
 * are attached to.
 * 
 * @see http://codex.wordpress.org/Function_Reference/WP_Query#Taxonomy_Parameters
 * @link http://wordpress.stackexchange.com/questions/16393/
 * 
 * @param string|array $taxonomy The taxonomy(s) of the terms you wish to obtain.
 * @param array $tax_query A tax query for the posts you want to make the association with.
 * @return array Array of term IDs.
 */
function get_terms_soft_associated( $taxonomy, $tax_query  )
{
    global $wpdb;

    // so you can pass a single tax query rather than wasted nested array
    if ( isset( $tax_query['taxonomy'] ) )
        $tax_query = array( $tax_query );

    $tax = new WP_Tax_Query( $tax_query );
    extract( $tax->get_sql( $wpdb->posts, 'ID' ) );

    if ( empty( $join ) || ( !$posts = $wpdb->get_col( "SELECT $wpdb->posts.ID FROM $wpdb->posts $join WHERE 1=1 $where" ) ) )
        return array();

    $taxonomy = implode( "','", array_map( 'esc_sql', ( array ) $taxonomy ) );
    $posts = implode( ',', wp_parse_id_list( $posts ) );

    return $wpdb->get_col(
        "SELECT DISTINCT t.term_id FROM $wpdb->terms AS t " .
        "INNER JOIN $wpdb->term_taxonomy AS tt ON tt.term_id = t.term_id " .
        "INNER JOIN $wpdb->term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id " .
        "WHERE tt.taxonomy IN('$taxonomy') AND tr.object_id IN($posts)"
    );
}

Vous pouvez également consulter le codex sur les requêtes relatives aux taxes pour obtenir de l'aide sur $tax_query. C’est la requête que nous utilisons pour filtrer les publications, avant de procéder à une recherche inversée afin de rassembler tous leurs termes pour une autre taxonomie.

Passons maintenant à la solution.

// suggestion 1 - for a single post
$product_cats = get_the_terms( get_the_ID(), 'myprod_category' );

// suggestion 2 - for a product category archive
$product_cats = get_queried_object_id();

// suggestion 3 - for all posts on the current page of an archive
foreach( $wp_query->posts as $_post ) {
    $_product_cats = get_the_terms( $_post->ID, 'myprod_category' );
    foreach ( $_product_cats as $_product_cat )
        $product_cats[] = $_product_cat->term_id;
}

// now get the 'associated' tag IDs
$product_assoc_tags = get_term_soft_association( 'product_tag', array(
    'taxonomy' => 'myprod_category',
    'field'    => 'term_id',
    'terms'    => $product_cats
) );

wp_tag_cloud( array( 'taxonomy' => 'product_tag', 'include' => $product_assoc_tags ) );

Notez que les suggestions sont des exemples montrant comment saisir toutes les catégories de produits sur lesquelles vous souhaitez effectuer une requête ultérieure, en fonction de votre situation et du ou des messages que vous souhaitez affecter au résultat (utilisez uniquement l'une des suggestions ou la vôtre!).

Si vous constatez que cela ne fonctionne pas comme vous le souhaitiez , il est probable que nous devons simplement ajuster la requête de taxe pour le second argument de la fonction.

* Note de bas de page: L'interrogation de post natif extrait toutes les données de post, alors que nous n'avons besoin que de travailler avec des identifiants. Économiser de la mémoire là où vous pouvez toujours vous aider, et comme @Daniel le dit, si nous parlons beaucoup de messages, nous parlons également beaucoup de mémoire.

Je dis aussi plus rapidement car, dans des conditions prédéfinies, nous utilisons beaucoup moins de requêtes et de traitements de bases de données que si nous avions utilisé des fonctions telles que get_terms() et get_posts().

5
TheDeadMedic

Si je vous comprends bien, je pense qu’il n’ya pas d’option directe.

Vous devez interroger tous les produits de la catégorie de votre choix, itérer ces enregistrements et obtenir les balises pour chaque produit. Ce sera lent si vous avez beaucoup de produits.

Quelque chose comme (c'est pour les catégories/tags ordinaires, vous devriez le modifier en fonction de vos taxonomies personnalisées)

    $posts = get_posts("cat=5&numberposts=-1");
$tags = Array();
foreach ($posts as $ipost){
    $posttags = get_the_tags($ipost->ID);
    foreach ($posttags as $posttag){
        if (!in_array($posttag->term_id, $tags)){
            array_Push($tags, $posttag->term_id);

        }
    }
}

Maintenant, vous avez dans $ tags les identifiants uniques des tags que vous recherchez.

Si vous avez beaucoup de produits, une requête SQL personnalisée est probablement une meilleure option.

1
MZAweb