WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I am trying to make a shortcode to print a list of post titles. This is what I have so far:

function test( $atts , $content = null ){

    $args = array( 'posts_per_page' => 3 );
    $lastposts = get_posts( $args );
    foreach ( $lastposts as $post )
        setup_postdata( $post );
        echo the_title();
add_shortcode( 'test', 'test' );

The problem I have is that all it does is print the title of the page calling the shortcode rather than the titles of the posts. I am sure I am missing something basic but after two hours of trying to work it out I thought it was time to get another set of eyes to look at it.

share|improve this question
Shortcode functions shouldn't actually output anyting, but return the desired output (Codex). – engelen Jun 15 '14 at 11:25
up vote 3 down vote accepted

I know this has been answered and the answer solved the issue but I found it very poor for any newbie that want to learn WordPress so I give mine in the hope it will be better:

  1. While get_posts() can do the job I would have used a simple query, for a secondary loop I prefer creating my own separate instance of the WP_Query
  2. Engelen is right there's no use for wp_reset_postdata() here
  3. The use of $content is also unecessary here, it's not a enclosing shortcode
  4. A shortcode returns something. On no account it should output something on its own. That could trigger unpredictable bugs. It's quite the same with add_filter()
  5. I know here it's just for test but generic names must be avoided for shortcodes because there is only one hook per shortcode so any shortcode that use the same name could override leading to unexpected results.

So for all these reasons I would recommand to do this instead :

add_shortcode( 'post_title', 'wpse_149667_post_title_sc' );
function wpse_149667_post_title_sc( $atts ){

    $args      = array( 'posts_per_page' => 3 );

    $lastposts = new WP_Query( $args );

    if( $lastposts->have_posts() ) :

     $output    = '<ul>';

      while( $lastposts->have_posts() ) : $lastposts->the_post();

         $output .= '<li>'.get_the_title($lastposts->post->ID).'</li>';


     $output .= '</ul>';

    else : 

        $output = 'There is currently no post to retrieve!';


    wp_reset_postdata();// more appropriate here

    return $output;

Hope this gives more explanations.

share|improve this answer

Try like this:

function test( $atts , $content = null ){

    $args = array( 'posts_per_page' => 3 );

    $lastposts = get_posts( $args );

    foreach ( $lastposts as $post )  {
        echo get_the_title($post->ID);

add_shortcode( 'test', 'test' );
share|improve this answer
Matt, just a tip here, your answer is considered as code dumping. You should always explain your code does. Please edit your answer and add all relevant info – Pieter Goosen Jun 15 '14 at 9:15
@PieterGoosen that maybe true but in true genius fashion he solved it. – Brett Jun 15 '14 at 9:17
Shortcode functions shouldn't actually output anyting, but return the desired output (Codex). Furthermore, the wp_reset_postdata is unnecessary if you're not setting up new post data. – engelen Jun 15 '14 at 11:24
Value should be returned instead of printing. This causes issues if someone hooks with the_content or similar filters. – Sisir Aug 10 '14 at 10:42

Your Answer


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.