如何仅列出分类法的子术语而不是其父母?


9

我正在admin中创建一个年龄选择菜单,该菜单是根据分类进行填充的age。分类法是分层的,如下所示:

  • 18-25(父母,ID 183)
    • 18(小孩)
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
  • 26-30(父母,ID 184)
    • 26
    • 27
    • 28
    • 29
    • 30

我只想列出孩子(18、19等),而不列出父母(18-25、26-30)等。目前,我正在使用get_termsparent参数,但它不接受超过1个父母ID。这是我到目前为止的内容,显示了18-25岁的孩子。

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

这是我想要的操作,但不受支持。我也尝试过使用数组,但是它也不起作用。

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

我看到有一个get_term_children函数,但是我不确定如何使用它,因为看起来它也只接受一个值。例如:在这个例子中,它将建立一个无序列表,但是我可以修改选择菜单。

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

调用get_terms两次并合并两个结果数组?
Mark Duncan

@Mark谢谢,我想这样做,但是即使将ID合并到数组中,我也看不到它的工作原理,因为它与手动列出它们的方式相同-183、184,但不会工作。
安德鲁

阅读了已接受的答案后,我现在从您想要所有术语(不包括顶级术语)的外观上完全不清楚您的问题get_terms。你的问题看,如果你是想.. 2个特定父项的所有儿童
马克·邓肯

Answers:


14

这应该为您工作:

$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,请客。我将您提供的内容混入了我想要的选择菜单中。好东西。
安德鲁

没问题。很高兴为您解决。
曼妮·弗勒蒙德

1
有关更有效的答案,请参见下面的karimhossenbux的答案。
dotancohen

$term->name在中无效get_term_link(),它仅接受术语ID,子弹或对象
Pieter Goosen

14

您也可以这样做:

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

我注意到,父级的“父级”字段等于0,而孩子的父级ID在其中。


4
接受的答案运行N次get_terms()调用,并在多项式时间内运行。此答案运行单个get_terms()调用,并在线性时间内运行。这是一个更好的答案。
dotancohen

@dotancohen您可以这样做,而不必在输出中排除顶级术语,可以通过将wpse_exclude_top参数添加到查询参数;-)中来删除顶级术语。但是,我确实同意,这比公认的答案要快
Pieter Goosen

1
@PieterGoosen:谢谢Pieter。我只是为字符串添加了4.4.2源代码wpse_exclude_topexclude_top但没有找到它们。谷歌也不知道这一点。它在哪里记录?
dotancohen

1
@dotancohen在我的回答中;-)
Pieter Goosen

5

我们可以通过terms_clauses在执行查询之前使用过滤器更改SQL查询来过滤掉顶级父级,从而排除它们。这样,我们无需在最终foreach循环中跳过父母,因为他们不在返回的术语数组中,这为我们节省了不必要的工作和编码

您可以尝试以下方法:

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

为了排除顶级父母,我们现在可以传递'wpse_exclude_top' => 1我们的参数数组。wpse_exclude_top上面的过滤器支持新参数

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

请注意,get_term_link()请勿仅接受子句,ID或完整的术语对象作为术语名称。为了提高性能,请始终将术语对象传递给get_term_link()是否存在术语对象(如本例所示


2

为什么不能仅将childless参数设置为true?

$ages = get_terms( array(
    'taxonomy' => 'age',
    'childless' => true
    )
);

childless参数设置为true意味着您只能深入1级,因此这不适用于具有3级或更多级的分类法。
GeckoSEO

-1

如果显示多个父母的孩子,则可以尝试此操作。显示提及字词ID子字词。

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

1
请解释为什么您认为此代码应该起作用。另外,我很确定硬编码解决方案不是最好的方法。
s_ha_dum 2015年

用ID提及问题,因此我回答了相关的想法。
杰基尔·侯赛因
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.