¿Cómo enumerar solo los términos secundarios de una taxonomía y no sus padres?

9

Estoy creando un menú de selección de edad en el administrador, poblado desde una taxonomía de age. La taxonomía es jerárquica de la siguiente manera:

  • 18-25 (padre, ID 183)
    • 18 (niño)
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
  • 26-30 (padre, ID 184)
    • 26
    • 27
    • 28
    • 29
    • 30

Me gustaría enumerar solo a los niños (18, 19, etc.) y no a los padres (18-25, 26-30), etc. Actualmente estoy usando get_termsel parentargumento, pero no acepta más de 1 ID de padre. Esto es lo que tengo hasta ahora, que muestra a los niños de 18 a 25 años.

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

Esto es lo que quiero que haga, pero no es compatible. También lo he intentado con una matriz, pero tampoco funciona.

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

Veo que hay una función get_term_children , pero tampoco estoy seguro de cómo usarla, ya que parece que solo acepta un valor también. Por ejemplo: en este ejemplo, crearía una lista desordenada pero podría modificar para seleccionar el menú.

<?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>';
?> 
Andrés
fuente
¿Llamar get_termsdos veces y fusionar las dos matrices de resultados?
Mark Duncan
@ Mark Gracias, pensé en hacerlo de esta manera, pero incluso si fusiono los ID en una matriz, no puedo ver cómo funcionaría porque sería lo mismo que enumerarlos manualmente: 183, 184, que no funciona t trabajo.
Andrew
Después de leer la respuesta aceptada, ahora me doy cuenta de que su pregunta no era del todo clara, por el aspecto de las cosas que quería todos los términos, excepto los de nivel superior ... (que puede hacer con una sola get_termsllamada). Tu pregunta se lee como si quisieras a todos los hijos de 2 términos de padres en particular ...
Mark Duncan

Respuestas:

14

Esto debería funcionar para usted:

$taxonomyName = "age";
//This gets top layer terms only.  This is done by setting parent to 0.  
$parent_terms = get_terms( $taxonomyName, array( 'parent' => 0, 'orderby' => 'slug', 'hide_empty' => false ) );   
echo '<ul>';
foreach ( $parent_terms as $pterm ) {
    //Get the Child terms
    $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>';
Manny Fleurmond
fuente
Gracias @Manny, trabajó un placer. Tomé lo que me proporcionó y lo mezclé en el menú de selección que estaba buscando. Buena cosa.
Andrew
No hay problema. Me alegro que funcionó para usted.
Manny Fleurmond
1
Vea la respuesta de karimhossenbux a continuación para obtener una respuesta mucho más eficiente.
dotancohen
$term->nameno es válido get_term_link(), solo acepta el término ID, babosa u objeto
Pieter Goosen
14

También puedes hacer:

$terms = get_terms($taxonomyName);
foreach($terms as $term) {
    if ($term->parent != 0) { // avoid parent categories
        //your instructions here
    }
}

He notado que el padre tiene el campo "padre" igual a 0, y un niño tiene su identificación padre en él.

karimhossenbux
fuente
44
La respuesta aceptada ejecuta N llamadas get_terms () y se ejecuta en tiempo polinómico. Esta respuesta ejecuta una sola llamada get_terms () y se ejecuta en tiempo lineal. Esta es una respuesta mucho mejor.
dotancohen
@dotancohen Puede hacer esto sin tener que excluir los términos de nivel superior en la salida, puede eliminar los términos de nivel superior con el wpse_exclude_topparámetro agregado a los argumentos de la consulta ;-). Sin embargo, estoy de acuerdo, esto es más rápido que la respuesta aceptada
Pieter Goosen
1
@PieterGoosen: Gracias Pieter. Acabo de asimilar el código fuente 4.4.2 para las cadenas wpse_exclude_topy exclude_topno las encontré. Tampoco Google sabe de eso. ¿Dónde está documentado?
dotancohen
1
@dotancohen en mi respuesta ;-)
Pieter Goosen
5

Podemos excluir a los padres de nivel superior al filtrarlos usando el terms_clausesfiltro para alterar la consulta SQL antes de que se ejecute. De esta manera, no necesitamos omitir a los padres en el foreachciclo final, ya que no están en la matriz de términos devueltos, esto nos ahorra trabajo y codificación innecesarios.

Puedes probar lo siguiente:

add_filter( 'terms_clauses', function (  $pieces, $taxonomies, $args )
{
    // Check if our custom arguments is set and set to 1, if not bail
    if (    !isset( $args['wpse_exclude_top'] ) 
         || 1 !== $args['wpse_exclude_top']
    )
        return $pieces;

    // Everything checks out, lets remove parents
    $pieces['where'] .= ' AND tt.parent > 0';

    return $pieces;
}, 10, 3 );

Para excluir a los padres de nivel superior, ahora podemos pasar 'wpse_exclude_top' => 1con nuestra variedad de argumentos. El nuevo wpse_exclude_topparámetro es compatible con el filtro de arriba

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

Solo una nota, get_term_link()no acepte el término nombre, solo, slug, ID o el término completo objeto. Para el rendimiento, siempre pase el término objeto a get_term_link()si el término objeto está disponible ( como en este caso )

Pieter Goosen
fuente
2

¿Por qué no puedes simplemente establecer el childlessargumento en verdadero?

$ages = get_terms( array(
    'taxonomy' => 'age',
    'childless' => true
    )
);
Yaron
fuente
establecer el childlessargumento en verdadero significa que solo puede ir a 1 nivel de profundidad, por lo que esto no funciona para taxonomías con 3 o más niveles.
GeckoSEO
-1

Si muestra varios hijos de padres, puede intentar esto. Muestra el término de mención ids término hijo.

$termIds = array(367, 366, 365, 364, 363, 362);
$taxonomyName = "age";

$args = array(
    'orderby'           => 'term_id', 
    'order'             => 'DESC',                      
    'hide_empty'        => false,                       
    'childless'         => false,
); 

$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>';
    }
  }
}
Jakir Hossain
fuente
1
Explica por qué crees que este código debería funcionar. Además, estoy bastante seguro de que una solución codificada no es la mejor manera.
s_ha_dum
La pregunta se menciona con ID, por esta razón he respondido pensar relacionado.
Jakir Hossain