Populating a page with content from post custom fields

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

Read More

Thanks.

Related posts

Leave a Reply

1 comment

  1. 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.