Help with Shortcode Functionality

I'm hoping someone who knows more than me about PHP and WordPress can help me out with this issue. I have a custom post type with posts I am displaying using the following code:

<?php $args = array( 'post_type' => 'upcoming_event', 'posts_per_page' => 3 );
 $loop = new WP_Query( $args );
  while ( $loop->have_posts() ) : $loop->the_post();
   echo '<div class="upcomingevents">';
   echo '<h4>';
   the_title();
   echo '</h4>';
   echo '<div class="upcomingeventimage">';
   the_post_thumbnail('medium');
   echo '</div>';
   echo '<div class="upcoming-event-entry-content">';
   the_content();
   echo '</div>';
   echo '</div>';
  endwhile;
 wp_reset_postdata();
?>

While this works fine in a php file, I'm trying to also make it easily accessible via shortcode. I made the shortcode, and the shortcode works, but every time I place it on a page/post and click "update" or "publish" it sends me to a page with this content printed on it (and only this content printed on it)... But it still saves it, and it still displays fine on the page I saved it on. I know I'm missing something, but I'm so novice at PHP that I don't know what it is.

Here's my shortcode:

// Shortcode for Upcoming Events
function upcoming_events_shortcode() {
  $args = array( 'post_type' => 'upcoming_event', 'posts_per_page' => 3 );
  $query = new WP_Query( $args );
  while ( $query->have_posts() ) : $query->the_post();
        echo '<div class="upcomingevents">';
        echo '<h4>';
        the_title();
        echo '</h4>';
        echo '<div class="upcomingeventimage">';
        the_post_thumbnail('medium');
        echo '</div>';
        echo '<div class="upcoming-event-entry-content">';
        the_content();
        echo '</div>';
        echo '</div>';
  endwhile;
 wp_reset_postdata();
}

add_shortcode('upcoming-events', 'upcoming_events_shortcode');

Thanks for any help! I'm learning as I go with this and usually I can Google my way out of most things, not this one though. Scratching my head on it.

Answers 2

  • Shortcodes should return a string, not echo data... so you have one of two options here:

    • Change all echo statements and all functions that 'echo' content to use with return (concatenate all on a string, then return it)
    • Use output buffering

    For output buffering, your code would end up like:

    function upcoming_events_shortcode() {
      $args = array( 'post_type' => 'upcoming_event', 'posts_per_page' => 3 );
      $query = new WP_Query( $args );
      ob_start();
      while ( $query->have_posts() ) : $query->the_post();
            echo '<div class="upcomingevents">';
            echo '<h4>';
            the_title();
            echo '</h4>';
            echo '<div class="upcomingeventimage">';
            the_post_thumbnail('medium');
            echo '</div>';
            echo '<div class="upcoming-event-entry-content">';
            the_content();
            echo '</div>';
            echo '</div>';
      endwhile;
     wp_reset_postdata();
     return ob_get_clean();
    }
    

    That way, all the echo'ed content will be captured by the output buffer.


  • Shortcode functions need to return a string rather than echo-ing output.

    Simply change all your echo statements into string concatenation and use functions that return rather than echo their results:

    // Shortcode for Upcoming Events
    function upcoming_events_shortcode() {
        $args = array( 'post_type' => 'upcoming_event', 'posts_per_page' => 3 );
        $query = new WP_Query( $args );
        while ( $query->have_posts() ) : $query->the_post();
            $output = '<div class="upcomingevents">';
            $output .= '<h4>';
            $output .= get_the_title();
            $output .= '</h4>';
            $output .= '<div class="upcomingeventimage">';
            $output .= get_the_post_thumbnail('medium');
            $output .= '</div>';
            $output .= '<div class="upcoming-event-entry-content">';
            $output .= get_the_content();
            $output .= '</div>';
            $output .= '</div>';
        endwhile;
        wp_reset_postdata();
    
        return $output;
    }
    
    add_shortcode('upcoming-events', 'upcoming_events_shortcode');
    

    Caveat: I've added get_ to your functions without testing. Check WP docs to make sure there aren't any differences between the functions.

    Read the developer docs on shortcodes to see how to include attributes so that you could, for example, vary the number of posts.


Related Questions