Search code examples
wordpressattributescustom-post-typeshortcode

WordPress Shortcode - Change Layout Based On Attribute


I have the following Custom Shortcode that displays a Custom Post Type of staff members in a defined taxonomy of "type". I'm trying to add a second attribute that will allow the user to define the layout style of the output, for example columns or rows. Here is what I envision the shortcode looking like:

[staff type="international" style="rows"]

I think I have all the coding for getting the attributes, including setting the default values, but I can't seem to figure out how to get an if statement in there to alter the output. It seems like it should go right before the first "$output .=" line.

function get_staff($atts) {
    extract( shortcode_atts( array( 
        'type' => 'international', 
        'style' => 'rows'
        ), $atts ) );

    add_filter( 'posts_orderby' , 'posts_orderby_lastname' );

    $loop = new WP_Query(
        array (
            'post_type' => 'staff',
            'orderby' => 'title',
            'staff-type' => $type,
            'style' => $style
        )
    );

    remove_filter( 'posts_orderby' , 'posts_orderby_lastname' );

    if ($loop->have_posts()) {
        $output = '<div class="staff">';

        while($loop->have_posts()){
            $loop->the_post();
            $meta = get_post_meta(get_the_id());
            // Attributes Array for Featured Image Below
            $attr = array(
                                'title' => get_the_title(),
                                'alt' => get_the_title(),
                                'class' => 'img_frame'
                            );
            $output .= '
                <div class="row-fluid" style="border-bottom: 1px solid #EEE; margin-bottom: 16px; padding-bottom: 16px;">
                <div class="span3">' . get_the_post_thumbnail($post->ID, 'small', $attr) . '</div>
                <div class="span9"><h3>' . get_the_title()  . '</h3>
                ' . get_the_content() . '
            </div></div>
        ';
    }
    $output .= "</div>";
} else {
    $output = 'No Staff Meet This Criteria Yet.';
}

return $output;
};

// Create Last Name Sort For Staff Custom Post Type
function posts_orderby_lastname ($orderby_statement) 
{
  $orderby_statement = "RIGHT(post_title, LOCATE(' ', REVERSE(post_title)) - 1) ASC";
    return $orderby_statement;
}


add_shortcode('staff', 'get_staff'); 

Solution

  • There are a few ways, depending on your coding style. You can check for the style param before starting to loop over posts. Another way is to do it after starting to loop. Sure, there's some code duplication, but it's easier to read and you'll have all the control you need over the exact markup you want to generate.

    $output = '<div class="staff">';
    
    if ($loop->have_posts()) {
    
        if($style == 'rows'){ // rows
            $output .= '<div class="layout-rows">';
            while( $loop->have_posts() ){
                // ...
            }
            $output .= "</div>";
        } elseif($style == 'columns') { // columns
            $output .= '<div class="layout-columns">';
            while( $loop->have_posts() ){
                // ...
            }
            $output .= "</div>";
        } else { // everything else
            $output .= '<div class="layout-default">';
            while( $loop->have_posts() ){
                // ...
            }
            $output .= "</div>";
        }
    
    } else {
        $output = 'No Staff Meet This Criteria Yet.';
    }
    
    $output .= "</div>";