Let's say i need to implement the following in WordPress :

I have a CPT named 'song' which are single songs from different artists. Sometimes songs may be grouped by albums, but not always.

Then i want to display latest releases on my homepage, like :


  • Song 1
  • song 2
  • Song 3
  • Album 1
    • Song 4
    • Song 7
    • Song 9
  • Song 6
  • Song 8
  • Song 10


So the rule would be to display all posts, from newest to oldest, but if they belong to a group, show the group instead, using the newest post date in group to sort the group with other posts.

Do you see how to create this in WordPress ? With a CTP + custom taxonomy? Or 2 CPT (1 album, 1 song)?

I have done this in the past using 2 CPT (1 album, 1 song):

  • You could add any number of songs to an album (with an ACF
  • On save_post action, i was adding a "parent_id" custom field to each children containing...the parent post ID.
  • Then i could achieve this with a WP_Query that asked for both CPT, but excluded posts with cusom field "parent_id" set.

But that sounded hacky at the time.. Do you see a better way to handle this behavior ? What if i want to use a taxonomy instead of a CPT ? In term of UX, users would prefer adding tags to songs instead of manually creating an album and adding songs to it.

It feels like a very common pattern yet i can't find the right way to do it :(

1 Answer 1


A custom taxonomy makes perfect sense - here's hoping I haven't missed something:

$songs = get_posts(
        'post_type' => 'song',

$index = array(); // Build an album_id => songs index
foreach ( $songs as $song ) {
    if ( $albums = get_the_terms( $song->ID, 'album' ) )
        $index[ $albums[0]->term_id ][] = $song;
        $index[ count( $index ) - 1 ][] = $song; // All on it's own. Negative index will not clash with album ID

echo '<ul class="songs">';
foreach ( $index as $album_id => $songs ) {
    if ( count( $songs ) > 1 ) // More than one song in this album?
        echo '<li class="album">' . get_term_field( 'name', $album_id, 'album' ) . '<ul>';

    foreach ( $songs as $song )
        echo '<li>' . get_the_title( $song ) . '</li>';

    if ( count( $songs ) > 1 )
        echo '</ul></li>';
echo '</ul>';

$index will inherit the order of $songs by however they were queried. When a song belongs to an album, any subsequent songs in that album get added to the stack & will appear in the nested list where the first song is indexed.

  • thanks, not exactly what i need but i get the idea, this is clever ! Commented Feb 19, 2015 at 12:03
  • you could also create a function and hook it to pre_get_posts
    – maioman
    Commented Feb 20, 2015 at 23:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.