Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I'm doing up a blog at the moment where each post is accompanied by the name of a song. Adding the songs to the posts is fairly easily done via custom fields.

However, I also need to have a page which lists all the songs in one place. Can this be done without using a plugin? If so, how? (And if not, then what's the best plugin to use to do it?)

Thanks.

share|improve this question
3  
44% accept rate!!! please go back to your old questions and accept some answers –  Bainternet Jun 18 '11 at 12:39
    
It can be difficult to understand how this place works, and politeness costs nothing. Consider going easy on the non-ninjas from time to time. –  snthr Jun 22 '11 at 14:33
    
i said "please" :) –  Bainternet Jun 22 '11 at 15:29
add comment

1 Answer

up vote 4 down vote accepted

I suggest using shortcode, as this'll easily allow you embed the song list anywhere in your content, in any page or post.

UPDATE: I got a little carried away, and ended up with this!

function song_list_shortcode( $attrs )
{
    $r = ( object )wp_parse_args( $attrs, array(
        'format' => '%post_title - %link',
        'link'   => '%song_key_name',
        'key'    => 'song_key_name'
    ) );

    $query = new WP_Query( array( 'meta_query' => array( array( 'key' => $r->key ) ), 'nopaging' => true, 'update_post_term_cache' => false ) );
    if ( !$query->have_posts() )
        return '';

    $meta_keys = array();
    foreach ( array( 'format', 'link' ) as $type ) {
        // find meta keys
        if ( !preg_match_all( '#%([a-z0-9_-]+)#', $r->$type, $_keys ) )
            continue;

        $_keys = array_flip( $_keys[1] );
        unset( $_keys['post_title'], $_keys['link'] ); // don't want these, not meta keys

        $meta_keys = $meta_keys + $_keys; // add new keys on to meta key stack
    }

    if ( !empty( $meta_keys ) )
        $meta_keys = array_keys( $meta_keys );

    $output = '<ul class="songs">';
    while ( $query->have_posts() ) {
        $query->the_post();

        $format = $r->format;
        $link = $r->link;

        if ( !empty( $meta_keys ) ) {
            // grab all meta data in one swoop (should be cached from query)
            $meta_data = get_post_custom( $query->post->ID );

            // swap out all meta key names with their actual value!
            foreach ( $meta_keys as $key ) {

                // using get_post_custom(), all meta data values are arrays
                if ( isset( $meta_data[ $key ][0] ) )
                    $value = esc_html( $meta_data[ $key ][0] );
                else
                    $value = ''; // meta key not found, so replace with blank

                list( $format, $link ) = str_replace( "%$key", $value, array( $format, $link ) );
            }
        }

        // swap out %post_title with actual post title
        list( $format, $link ) = str_replace( '%post_title', get_the_title(), array( $format, $link ) );

        // swap out %link in $format with actual $link
        $output .= '<li>' . str_replace( '%link', '<a href="' . get_permalink() . '">' . $link . '</a>', $format ) . '</li>';
    }

    wp_reset_postdata();

    $output .= '</ul>';
    return $output;
}
add_shortcode( 'song-list', 'song_list_shortcode' );

You can use it like so;

[song-list format="%post_title - %link - %song_date_meta_key"]
// The post title - <a href="/post/">Song Name</a> - Song Date

See how using % indicates a meta key, which'll get swapped out with the value at run-time.

Also note that %post_title and %link are two special parameters that get swapped with the post title and anchor link, respectively.

You can also format the contents of the link text in the same way;

[song-list link="Date: %song_date_meta_key"]
// Post Title <a href="/post/">Date: Song Date</a>

Finally, the key attribute controls which posts are retrieved.

[song-list key="song_name"]
// Retrieves all posts with the meta key 'song_name'

I'd recommend replacing the hard-coded defaults at the beginning of the function with your most often used parameters.

share|improve this answer
    
Hi TheDeadMedic, thanks for that, it seems to be what I'm after. Is there any way to put the title of the post into the <li> before the song name? I tried with the_title but it ain't working... –  snthr Jun 18 '11 at 18:12
    
You want get_the_title() - see revised answer. –  TheDeadMedic Jun 18 '11 at 18:17
    
That's fantastic, thanks. Aaaand... one last thing. :) Is there a way to output another custom field in the same <li>? Say, to include the name of the band the song is by, or the date it was released, assuming that they're available as separate custom fields accompanying the posts? Thanks! –  snthr Jun 19 '11 at 18:20
    
So like, <li>TITLE - [SONG NAME LINK] - DATE</li>? Would you want to control what appears through the shortcode (for example, `[song-list show="name,date"]), or just hardcode it in the function? –  TheDeadMedic Jun 19 '11 at 18:47
    
Yep, that's what I'm after. If it could be included in the shortcode (and so could be easily edited or expanded in future) that would be best, but I could live with it being hardcoded in the function. –  snthr Jun 19 '11 at 19:28
show 6 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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