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 trying to write a shortcode that will allow the option to display all users or show a singular user, defined by a user id or "nicename".

The shortcode would look something like this: [staff display="all"] or [staff display="single" user="3"]

I have a standard shortcode working that displays all users, but I'd like to adapt it for the options in the above examples. I'm not sure the best route to integrate it all together.

Here's my shortcode function as it stands now, which works for [staff]:

function list_users(){ 
    $args = array(
        'orderby' => 'ID',
        'order' => 'ASC'
    );
    $users = get_users($args);

    echo '<ul class="staff">';
        foreach( $users as $user ){ 
        $user_info = get_userdata($user->ID);
            echo '<li>';
            echo '<a href="'.get_home_url().'/author/'.$user_info->user_nicename.'" class="staff-image">';
            echo mt_profile_img( $user->ID, array('size' => 'Services',));
            echo '</a>';
            echo '<div class="staff-info"><a href="'.get_home_url().'/author/'.$user_info->user_nicename.'" class="staff-name"><h2>'.$user->display_name.'</h2></a>';
            echo '<div class="service-certs">';
            echo the_field('certifications','user_'.$user->ID);
            echo '</div>';
            echo '<p class="service-excerpt">';
            echo the_field('short_bio','user_'.$user->ID);
            echo '</p>';
            echo '<a href="'.get_home_url().'/author/'.$user_info->user_nicename.'" class="more-staff-bio">Read more from ' . $user_info->user_firstname . '</a></div><div style="clear: both;"></div>';
            echo '</li>';
        }
    echo '</ul>';

}
add_shortcode('staff', 'list_users');

EDIT Based on the suggestions from an answer below, here are my new functions

//* Shortcode for getting users
function display_all_users(){ 
    $args = array(
        'orderby' => 'ID',
        'order' => 'ASC'
    );
    $users = get_users($args);

    echo '<ul class="staff">';
        foreach( $users as $user ){ 
        $user_info = get_userdata($user->ID);
            echo '<li>';
            echo '<a href="'.get_home_url().'/author/'.$user_info->user_nicename.'" class="staff-image">';
            echo mt_profile_img( $user->ID, array('size' => 'Services',));
            echo '</a>';
            echo '<div class="staff-info"><a href="'.get_home_url().'/author/'.$user_info->user_nicename.'" class="staff-name"><h2>'.$user->display_name.'</h2></a>';
            echo '<div class="service-certs">';
            echo the_field('certifications','user_'.$user->ID);
            echo '</div>';
            echo '<p class="service-excerpt">';
            echo the_field('short_bio','user_'.$user->ID);
            echo '</p>';
            echo '<a href="'.get_home_url().'/author/'.$user_info->user_nicename.'" class="more-staff-bio">Read more from ' . $user_info->user_firstname . '</a></div><div style="clear: both;"></div>';
            echo '</li>';
        }
    echo '</ul>';
}


function list_of_users( $atts ){
    // extract and set defaults
    extract( shorcode_atts( array(
        'display' => 'all',
        'user' => 30
    ), $atts, 'staff' ) );

    // now vary your output based on $display att
    switch ( $display ) {

        case 'all':
            $content = display_all_users();
            break;

        case 'single':
            $content = display_single_user( (int) $user );
            break;

        default:
            break;
    }

    // give the shortcode something to output
    return $content;
}
add_shortcode('staff', 'list_of_users');

EDIT 2 I got it to work, however, the output of my single function is dumping the contents outside of the div wraps that its supposed to be in.

//* Shortcode for getting users
function list_of_users( $atts = array(), $content = null ){
    extract(shortcode_atts(
        array(
            'display' => 'all',
            'user' => '30'
        ),
        $atts
    ));

    switch ( $display ) {

        case 'all':
            $content = display_all_users();
            break;

        case 'single':
            $content = display_single_user( (int) $user );
            break;

        default:
            break;
    }

    return $all;
}
add_shortcode('staff', 'list_of_users');

function display_all_users(){ 
    $args = array(
        'orderby' => 'ID',
        'order' => 'ASC'
    );
    $users = get_users($args);

    echo '<ul class="staff">';
        foreach( $users as $user ){ 
        $user_info = get_userdata($user->ID);
            echo '<li>';
            echo '<a href="'.get_home_url().'/author/'.$user_info->user_nicename.'" class="staff-image">';
            echo mt_profile_img( $user->ID, array('size' => 'Services',));
            echo '</a>';
            echo '<div class="staff-info"><a href="'.get_home_url().'/author/'.$user_info->user_nicename.'" class="staff-name"><h2>'.$user->display_name.'</h2></a>';
            echo '<div class="service-certs">';
            echo the_field('certifications','user_'.$user->ID);
            echo '</div>';
            echo '<p class="service-excerpt">';
            echo the_field('short_bio','user_'.$user->ID);
            echo '</p>';
            echo '<a href="'.get_home_url().'/author/'.$user_info->user_nicename.'" class="more-staff-bio">Read more from ' . $user_info->user_firstname . '</a></div><div style="clear: both;"></div>';
            echo '</li>';
        }
    echo '</ul>';
}

function display_single_user(){
    extract(shortcode_atts(
        array(
            'display' => 'all',
            'user' => '30'
        ),
        $atts
    ));

    $output = mt_profile_img( $user, array('size' => 'Services',)).the_field('short_bio','user_'.$user);
}

EDIT #3 I have the output working and "buffering to the right area. But I noticed that the variable user used in the shortcode does not get passed to the single function.

    //* Shortcode for getting users
function list_of_users( $atts = array(), $content = null ){
    extract(shortcode_atts(
        array(
            'display' => 'all',
            'user' => '30'
        ),
        $atts
    ));
    ob_start();
        switch ( $display ) {
            case 'all':
                $content = display_all_users();
                break;
            case 'single':
                $content = display_single_user( (int) $user );
                break;
            default:
                break;
        }

    $output = ob_get_clean();

    return $all.$output;
}
add_shortcode('staff', 'list_of_users');

function display_all_users(){ 
    $args = array(
        'orderby' => 'ID',
        'order' => 'ASC'
    );
    $users = get_users($args);

    echo '<ul class="staff">';
        foreach( $users as $user ){ 
        $user_info = get_userdata($user->ID);
            echo '<li>';
            echo '<a href="'.get_home_url().'/author/'.$user_info->user_nicename.'" class="staff-image">';
            echo mt_profile_img( $user->ID, array('size' => '250x250',));
            echo '</a>';
            echo '<div class="staff-info"><a href="'.get_home_url().'/author/'.$user_info->user_nicename.'" class="staff-name"><h2>'.$user->display_name.'</h2></a>';
            echo '<div class="service-certs">';
            echo the_field('certifications','user_'.$user->ID);
            echo '</div>';
            echo '<p class="service-excerpt">';
            echo the_field('short_bio','user_'.$user->ID);
            echo '</p>';
            echo '<a href="'.get_home_url().'/author/'.$user_info->user_nicename.'" class="more-staff-bio">Read more from ' . $user_info->user_firstname . '</a></div><div style="clear: both;"></div>';
            echo '</li>';
        }
    echo '</ul>';
}

function display_single_user($args){
    $args = extract(shortcode_atts(
        array(
            'display' => 'all',
            'user' => '30'
        ),
        $atts, 'staff'
    ));

    echo'<div class="home-profile-image">';
    echo mt_profile_img( $user, array('size' => '175x175',));
    echo '</div><div class="home-short-bio">';
    echo the_field('short_bio','user_'.$user);
    echo'</div><a href="'.get_home_url().'/our-team/" class="button">Read more staff bios</a>';
}

I'm still new to writing functions, so forgive me if my syntax isn't the most optimal for its use.

share|improve this question

2 Answers 2

up vote 1 down vote accepted

Regarding Edit #3 I would rewrite it like this:

//* Shortcode for getting users
function list_of_users( $atts ) {

    extract( shortcode_atts(
        array(
            'display' => 'all',
            'user' => '30'
        ),
        $atts
    ));

    $content = '';
    switch ( $display ) {
        case 'all':
            $content = display_all_users();
            break;
        case 'single':
            $content = display_single_user( (int) $user );
            break;
        default:
        break;
    }
    return $content;
}
add_shortcode('staff', 'list_of_users');

function display_all_users(){ 
    $args = array(
        'orderby' => 'ID',
        'order' => 'ASC'
    );
    $users = get_users( $args );

    $html = '<ul class="staff">';
        foreach( $users as $user ){ 
            $user_info = get_userdata($user->ID);
            $html .= '<li>';
            $html .= '<a href="'.get_home_url().'/author/'.$user_info->user_nicename.'" class="staff-image">';
            $html .= mt_profile_img( $user->ID, array('size' => '250x250', 'echo' => false));
            $html .= '</a>';
            $html .= '<div class="staff-info"><a href="'.get_home_url().'/author/'.$user_info->user_nicename.'" class="staff-name"><h2>'.$user->display_name.'</h2></a>';
            $html .= '<div class="service-certs">';
            $html .= get_field('certifications','user_'.$user->ID);
            $html .= '</div>';
            $html .= '<p class="service-excerpt">';
            $html .= get_field('short_bio','user_'.$user->ID);
            $html .= '</p>';
            $html .= '<a href="'.get_home_url().'/author/'.$user_info->user_nicename.'" class="more-staff-bio">Read more from ' . $user_info->user_firstname . '</a></div><div style="clear: both;"></div>';
            $html .= '</li>';
        }
    $html .= '</ul>';
    return $html;
}

function display_single_user( $user_id = 30 ){

    $html = '<div class="home-profile-image">';
    $html .=  mt_profile_img( $user_id, array('size' => '175x175', 'echo' => false));
    $html .= '</div><div class="home-short-bio">';
    $html .=  get_field('short_bio','user_'.$user_id);
    $html .= '</div><a href="'.get_home_url().'/our-team/" class="button">Read more staff bios</a>';

    return $html;
}
share|improve this answer

You should take a look at the first example for the shortcode_atts() page in the Codex:

function bartag_func( $atts ) {
    extract( shortcode_atts( array(
        'foo' => 'no foo',
        'bar' => 'default bar',
    ), $atts, 'bartag' ) );
    // etc...

That great little function parses and sets defaults for a shortcode with two potential arguments:

[bartag foo="" bar=""]

If either attribute is not provided, the foo and bar arguments are set to the defaults provided in the array.

So for your shortcode, I could imagine something like this (untested psuedo-ish code):

function my_list_users( $atts ){
    // extract and set defaults
    extract( shorcode_atts( array(
        'display' => 'all',
        'user' => 1
    ), $atts, 'list_users' ) );

    // now vary your output based on $display att
    switch ( $display ) {

        case 'all':
            $content = my_display_all_users();
            break;

        case 'single':
            $content = my_display_single_user( (int) $user );
            break;

        default:
            // do something?
            break;
    }

    // give the shortcode something to output
    return $content;
}
add_shortcode( 'my_list_users', 'my_list_users' );

For cleanliness, I'd probably split out the functions for listing all users and a single user into separate functions and call them from the shortcode function as done above. Also, it's generally good practice to prefix your functions (something like the my_ above) to prevent any collisions with other shortcodes and functions.

share|improve this answer
    
Thanks @mrwweb. It doesn't quite work, i've updated my original question with the new code based on your suggestions...maybe i did something wrong? The other part of my question still seems a mystery on how to get the user id or name form the shortcode and pass that into the single function. Ideas? –  NW Tech Oct 17 '13 at 19:42
    
FWIW, here is the page that I'm testing this on: nwtd.co/northwest-massage/our-team –  NW Tech Oct 17 '13 at 20:12
    
Two things: 1) Shortcodes need to return everything and that includes functions you use in shortcodes (unless you're output buffering, but I try to avoid that). 2) How to query a specific user is really a different question that how to get a shortcode to accept and use an option which was the focus of this question. I'd start a new question once you've got everything else working. –  mrwweb Oct 17 '13 at 21:56
    
understood on a new question. I did however get this workign with some tinkering. My altered code has been added tot he original question as Edit #2. But my output seems to be escaping the contents from the div it's in. Any thoughts? –  NW Tech Oct 17 '13 at 22:00
    
The display_single_user function doesn't accept any arguments. It also doesn't return anything. And make sure mt_user_img doesn't echo its output either. –  mrwweb Oct 18 '13 at 14:23

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.