Get terms within a custom taxonomy

In wordpress a parent for a term is always referred to the same taxonomy. So as you already understand what you need is create a texonomy in which parent term rapresents a ‘School’ and a child term rapresents a ‘Group.’ Maybe a third-level-term rapresents a ‘Sub-Group’ or something else.

Doing so and using the argument parent and/or child_of in get_terms function or using get_term_children function is easy retrieve the children (or grandchildren) of a term.

But probably you will need some trick to use it at the best.

Let’s assume your taxonomy is called ‘organization’ and first level is for schools, second for groups, third for sub-groups.

Now assuming you have a custom post type ‘Students’ and you attach the terms of ‘organization’ taxonomy to students.

If you visit a link similar to www.site.com/organization/nehight/ it show an archive of all students in ‘NE High’ school. When you visit www.site.com/organization/nehight/group-name it show an archive of all students in a group called ‘Group Name’. And so on for sub groups.

But once taxonomy is the same, if you create a template file called ‘taxonomy-organization.php’ it will handle all requests for school, groups and subgroups.

If in the template you want to show a title like NE High School or Group Name, how can you know if the term requested is a school, a group or a subgroup?

A function like following can help you:

function organization_is( $term ) {
  if ( is_int($term) ) $term = get_term( $term, 'organization' );
  if ( ! is_object($term) || is_wp_error() ) return;
  if ( $term->parent == 0 ) return 'school';
  if ( organization_is($term->parent) == 'school' ) return 'group';
  return 'subgroup';
}

in the template file just use it like so:

$term = get_queried_object();

switch ( organization_is( $term ) ) {
  case 'school' :
    echo 'All Students for School: ' . $term->name;
    break;
  case 'group' :
    echo 'All Students for Group: ' . $term->name;
    break;
  case 'subgroup' :
    echo 'All Students for Sub-Group: ' . $term->name;
    break;
}

Another situation you can need a trick like the previous, is in the single student view. There you will probably want to show something like:

  • School: NE High
  • Groups: A group, Another Group
  • Sub-Group: Awesome Sub-Group

Using get_the_terms( $studid, 'organization' ) you retrieve all the terms attached to student, but how can you know if a term is of first, second or third level (and so if is a school, a group or a subgroup)?

You can write another function, that make use of the previous:

  function get_the_organization( $studid ) {
    $terms = get_the_terms( $studid, 'organization' );
    $organization = array(
      'school' => array(), 'group' => array(), 'subgroup' => array()
    );
    foreach ( $terms as $term ) {
      if ($term->parent == 0 ) {
        $organization['school'][] = $term;
      } elseif ( organization_is( $term->parent ) == 'group' ) {
        $organization['group'][] = $term;
      } else {
        $organization['subgroup'][] = $term;
      }    
    }
    return $organization;
  }

Now for every student you can assign multiple terms of every level, then calling the function above you will get an array containing 3 other arrays: one for shools, one for groups an one for sub-groups of the student.

A simply cycle through this array in the single student template and you can output whatever you want.

Hope it helps.