Cum să listezi doar termenii copil ai unei taxonomii și nu părinții lor?

24 iul. 2011, 15:51:21
Vizualizări: 94.2K
Voturi: 12

Creez un meniu de selectare a vârstei în administrare, populat dintr-o taxonomie age. Taxonomia este ierarhică după cum urmează:

  • 18-25 (părinte, ID 183)
    • 18 (copil)
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
  • 26-30 (părinte, ID 184)
    • 26
    • 27
    • 28
    • 29
    • 30

Vreau să listezi doar copiii (18, 19 etc) și nu părinții (18-25, 26-30) etc. Momentan folosesc get_terms cu argumentul parent, dar nu acceptă mai mult de 1 ID de părinte. Iată ce am până acum, care afișează copiii din 18-25.

    $ages = get_terms( 'age', array(
        'hide_empty' => 0,
        'parent' => '183',
    ));

Iată ce vreau să fac, dar nu este suportat. Am încercat și cu un array dar nu funcționează.

    $ages = get_terms( 'age', array(
        'hide_empty' => 0,
        'parent' => '183,184',
    ));

Am văzut că există o funcție get_term_children dar nu sunt sigur cum să o folosesc deoarece pare să accepte doar o singură valoare. Ex: În acest exemplu ar construi o listă neordonată dar aș putea modifica pentru un meniu de selectare.

<?php
    $termID = 183;
    $taxonomyName = "age";
    $termchildren = get_term_children( $termID, $taxonomyName );

    echo '<ul>';
    foreach ($termchildren as $child) {
    $term = get_term_by( 'id', $child, $taxonomyName );
    echo '<li><a href="' . get_term_link( $term->name, $taxonomyName ) . '">' . $term->name . '</a></li>';
    }
    echo '</ul>';
?> 
3
Comentarii

Apelează get_terms de două ori și unifică cele două array-uri de rezultate?

t31os t31os
24 iul. 2011 18:21:36

@Mark Mulțumesc, m-am gândit să fac asta, dar chiar dacă unific ID-urile într-un array, nu văd cum ar funcționa pentru că ar fi la fel ca și cum le-aș lista manual - 183, 184, ceea ce nu funcționează.

Andrew Andrew
25 iul. 2011 02:43:27

După ce am citit răspunsul acceptat, acum înțeleg că întrebarea ta nu a fost pe deplin clară, se pare că voiai toate termenii, excluzând cele de nivel superior.. (ceea ce poți face cu un singur apel get_terms). Întrebarea ta părea să sugereze că doreai toți copiii a doi termeni părinți specifici..

t31os t31os
26 iul. 2011 19:03:00
Toate răspunsurile la întrebare 6
4
19

Acest lucru ar trebui să funcționeze pentru tine:

$taxonomyName = "age";
//Aceasta obține doar termenii de nivel superior. Acest lucru se realizează prin setarea părintelui la 0.
$parent_terms = get_terms(
  $taxonomyName,
  array(
    'parent' => 0,
    'orderby' => 'slug',
    'hide_empty' => false
  )
);

echo '<ul>';
foreach ( $parent_terms as $pterm ) {
  //Obține termenii copii
  $terms = get_terms(
    $taxonomyName,
    array(
      'parent' => $pterm->term_id,
      'orderby' => 'slug',
      'hide_empty' => false
    )
  );
  foreach ( $terms as $term ) {
    echo '<li><a href="'. get_term_link($term) . '">'. $term->name .'</a></li>';
  }
}
echo '</ul>';
25 iul. 2011 06:46:05
Comentarii

Mulțumesc @Manny, a funcționat perfect. Am luat ceea ce ai oferit și l-am adaptat la meniul select la care mă uitam. Excelent lucru.

Andrew Andrew
25 iul. 2011 07:57:08

Nicio problemă. Mă bucur că a funcționat pentru tine.

Manny Fleurmond Manny Fleurmond
25 iul. 2011 08:21:17

Vezi răspunsul lui karimhossenbux mai jos pentru un răspuns mult mai eficient.

dotancohen dotancohen
15 mar. 2016 18:47:22

$term->name este invalid în get_term_link(), funcția acceptă doar ID-ul termenului, slug-ul sau obiectul

Pieter Goosen Pieter Goosen
15 mar. 2016 20:03:04
4
17

Puteți face și asta:

$terms = get_terms($taxonomyName);
foreach($terms as $term) {
    if ($term->parent != 0) { // evită categoriile părinte
        //aici instrucțiunile tale
    }
}

Am observat că categoriile părinte au câmpul "parent" egal cu 0, iar o categorie copil are ID-ul părintelui în acest câmp.

15 mar. 2016 18:32:03
Comentarii

Răspunsul acceptat efectuează N apeluri get_terms() și rulează în timp polinomial. Acest răspuns efectuează un singur apel get_terms() și rulează în timp liniar. Acesta este un răspuns mult mai bun.

dotancohen dotancohen
15 mar. 2016 18:46:41

@dotancohen Puteți face acest lucru fără a fi nevoie să excludeți termenii de nivel superior la ieșire, puteți elimina termenii de nivel superior cu parametrul wpse_exclude_top adăugat la argumentele interogării ;-). Sunt totuși de acord, acest lucru este mai rapid decât răspunsul acceptat

Pieter Goosen Pieter Goosen
15 mar. 2016 20:05:07

@PieterGoosen: Mulțumesc Pieter. Tocmai am căutat în codul sursă 4.4.2 șirurile wpse_exclude_top și exclude_top dar nu le-am găsit. Nici google nu știe despre asta. Unde este documentat?

dotancohen dotancohen
16 mar. 2016 10:23:06

@dotancohen în răspunsul meu ;-)

Pieter Goosen Pieter Goosen
16 mar. 2016 10:24:53
1

Putem exclude părinții de nivel superior prin filtrarea lor folosind filtrul terms_clauses pentru a modifica interogarea SQL înainte de execuție. În acest fel, nu este nevoie să sărim peste părinți în bucla finală foreach, deoarece aceștia nu vor fi prezenți în array-ul returnat de termeni. Acest lucru ne scutește de munca și codul inutil.

Puteți încerca următoarele:

add_filter( 'terms_clauses', function (  $pieces, $taxonomies, $args )
{
    // Verificăm dacă argumentul nostru personalizat este setat și egal cu 1, altfel ieșim
    if (    !isset( $args['wpse_exclude_top'] ) 
         || 1 !== $args['wpse_exclude_top']
    )
        return $pieces;

    // Totul este în regulă, să eliminăm părinții
    $pieces['where'] .= ' AND tt.parent > 0';

    return $pieces;
}, 10, 3 );

Pentru a exclude părinții de nivel superior, putem acum pasa 'wpse_exclude_top' => 1 în array-ul de argumente. Noul parametru wpse_exclude_top este suportat de filtrul de mai sus.

$terms = get_terms( 'category', ['wpse_exclude_top' => 1] );
if (    $terms
     && !is_wp_error( $terms )
) {
    echo '<ul>';
        foreach ($terms as $term) {
            echo '<li><a href="' . get_term_link( $term ) . '">' . $term->name . '</a></li>';  
        }
    echo '</ul>';
}

O mică observație, get_term_link() nu acceptă numele termenului, ci doar slug-ul, ID-ul sau obiectul termen complet. Pentru performanță, este recomandat să pasați întotdeauna obiectul termen către get_term_link() dacă acesta este disponibil (ca în acest caz).

15 mar. 2016 20:01:59
Comentarii

Bună, ai vreo idee cum să rezolv această problemă? stackoverflow.com/q/70327174/9036446

evavienna evavienna
17 dec. 2021 07:22:10
3

De ce nu poți seta pur și simplu argumentul childless la true?

$ages = get_terms( array(
    'taxonomy' => 'age',
    'childless' => true
    )
);
20 oct. 2016 02:20:19
Comentarii

setarea argumentului childless la true înseamnă că poți merge doar cu 1 nivel în adâncime, deci nu funcționează pentru taxonomii cu 3 sau mai multe niveluri.

GeckoSEO GeckoSEO
23 apr. 2018 18:58:19

A funcționat perfect pentru nevoile mele! Mulțumesc!

jsmod jsmod
11 oct. 2020 19:54:13

De asemenea, va returna părinți fără copii în loc de copii fără părinți.

certainlyakey certainlyakey
2 ian. 2021 23:15:05
0
$taxonomy = 'age'; // Taxonomia pentru grupele de vârstă
foreach( get_terms( [ 'taxonomy' => $taxonomy, 'parent' => 0 ] ) as $parent )
{
    // Obține termenii copil pentru fiecare termen părinte
    foreach( get_terms( [ 'taxonomy' => $taxonomy, 'parent' => $parent->term_id ] ) as $child )
    {
        // faci operații aici
        print_r( $child ); // Afișează detaliile termenului copil
    }
}
16 apr. 2024 13:16:09
2
-1

Dacă dorești să afișezi mai mulți copii ai unui părinte, poți încerca această metodă. Afișează termenii copii ai ID-urilor menționate.

$termIds = array(367, 366, 365, 364, 363, 362);
$taxonomyName = "age"; // Taxonomia (de exemplu, vârste)

$args = array(
    'orderby'           => 'term_id', // Ordonează după ID-ul termenului
    'order'             => 'DESC',    // Ordine descrescătoare                     
    'hide_empty'        => false,     // Afișează și termenii goi                   
    'childless'         => false,     // Include termenii care au copii
); 

$terms = get_terms( $taxonomyName, $args );

if ( ! empty( $terms ) && ! is_wp_error( $terms ) ){
$inc = 1;
foreach ( $terms as $term ) {                          
 if (in_array($term->parent, $termIds)) {
  echo '<option value="'.$term->term_id.'"><font><font>'.$term->name.'</font></font></option>';
    }
  }
}
29 dec. 2015 15:16:42
Comentarii

Te rog să explici de ce crezi că acest cod ar trebui să funcționeze. De asemenea, sunt destul de sigur că o soluție hard-codată nu este cea mai bună metodă.

s_ha_dum s_ha_dum
29 dec. 2015 16:23:58

Întrebarea menționează ID-uri, din acest motiv am răspuns în legătură cu acest aspect.

Jakir Hossain Jakir Hossain
30 dec. 2015 17:23:33