Cum să listezi doar termenii copil ai unei taxonomii și nu părinții lor?
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>';
?>

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>';

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.

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

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.

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 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

@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?

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).

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

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.

$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
}
}

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>';
}
}
}

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ă.
