Como listar apenas os termos filhos de uma taxonomia e não seus pais?

9

Estou criando um menu de seleção de idade no administrador, preenchido a partir de uma taxonomia de age. A taxonomia é hierárquica da seguinte maneira:

  • 18-25 (pai, ID 183)
    • 18 (criança)
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
  • 26-30 (pai, ID 184)
    • 26
    • 27
    • 28.
    • 29
    • 30

Gostaria de listar apenas os filhos (18, 19, etc.) e não os pais (18-25, 26-30) etc. Atualmente, estou usando get_termso parentargumento, mas ele não aceita mais de um ID dos pais. Aqui está o que tenho até agora, que mostra as crianças de 18 a 25 anos.

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

Aqui está o que eu quero que ele faça, mas não é suportado. Eu também tentei com uma matriz, mas também não funciona.

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

Vejo que existe uma função get_term_children , mas não tenho certeza de como usá-la, pois parece que ela também aceita apenas um valor. Por exemplo: neste exemplo, criaria uma lista não ordenada, mas eu poderia modificar o menu de seleção.

<?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>';
?> 
Andrew
fonte
Ligar get_termsduas vezes e mesclar as duas matrizes de resultados?
MarkDuncan
@ Mark Obrigado, pensei em fazê-lo desta maneira, mas mesmo se mesclar os IDs em uma matriz, não consigo ver como funcionaria porque seria o mesmo que listá-los manualmente - 183, 184, o que não acontece ' não funciona.
21411 Andrew Andrew
Depois de ler a resposta aceita, agora percebo que sua pergunta não era totalmente clara, desde a aparência das coisas que você queria em todos os termos, excluindo os de nível superior .. (o que você pode fazer com uma única get_termsligação). Sua pergunta lido como se estivesse querendo todas as crianças de 2 mandatos pais particulares ..
Mark Duncan

Respostas:

14

Isso deve funcionar para você:

$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
fonte
Obrigado @Manny, trabalhou um prazer. Peguei o que você forneceu e misturei no menu de seleção que eu procurava. Coisas boas.
28411 Andrew
Sem problemas. Que bom que funcionou para você.
Manny Fleurmond
11
Veja a resposta de karimhossenbux abaixo para obter uma resposta muito mais eficiente.
dotancohen
$term->nameestá em inválido get_term_link(), só aceita o termo ID, lesma ou objeto
Pieter Goosen
14

Você também pode fazer:

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

Observei que o pai tem o campo "pai" igual a 0, e um filho tem seu ID pai.

karimhossenbux
fonte
4
A resposta aceita executa N chamadas de get_terms () e é executada em tempo polinomial. Esta resposta executa uma única chamada get_terms () e é executada em tempo linear. Esta é uma resposta muito melhor.
dotancohen
@dotancohen Você pode fazer isso sem ter que excluir os termos de nível superior na saída. Você pode remover os termos de nível superior com o wpse_exclude_topparâmetro adicionado aos argumentos da consulta ;-). No entanto eu concordo, este é mais rápido do que a resposta aceita
Pieter Goosen
11
@ PieterGoosen: Obrigado Pieter. Eu apenas preenchi o código-fonte 4.4.2 para as strings wpse_exclude_tope, exclude_topmas não as encontrei. O Google também não sabe disso. Onde está documentado?
dotancohen 16/03/16
11
@dotancohen na minha resposta ;-)
Pieter Goosen
5

Podemos excluir os pais de nível superior filtrando-os usando o terms_clausesfiltro para alterar a consulta SQL antes da execução. Dessa forma, não precisamos ignorar os pais no foreachloop final, pois eles não estão no conjunto de termos retornado, economizando trabalho e codificação desnecessários.

Você pode tentar o seguinte:

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 os pais de nível superior, agora podemos passar 'wpse_exclude_top' => 1com nossa matriz de argumentos. O novo wpse_exclude_topparâmetro é suportado pelo filtro acima

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

Apenas uma observação: get_term_link()não aceite o nome do termo, apenas slug, ID ou o objeto do termo completo. Para desempenho, sempre passe sempre o termo objeto para get_term_link()se o termo objeto estiver disponível ( como neste caso )

Pieter Goosen
fonte
2

Por que você não pode simplesmente definir o childlessargumento como verdadeiro?

$ages = get_terms( array(
    'taxonomy' => 'age',
    'childless' => true
    )
);
Yaron
fonte
definir o childlessargumento como true significa que você pode apenas atingir um nível de profundidade; portanto, isso não funciona para taxonomias com 3 ou mais níveis.
GeckoSEO
-1

Se você exibir vários filhos dos pais, tente isso. Exiba os IDs dos termos de menção e termo filho.

$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
fonte
11
Por favor, explique por que você acha que esse código deve funcionar. Além disso, tenho certeza de que uma solução codificada não é a melhor maneira.
s_ha_dum
A pergunta menciona ids, por esse motivo, respondi a pensamentos relacionados.
Jakir Hossain