List Posts Alphabetically Under First Letter Of Title

Here is sample code to list posts alphabetically under the first letter of the title.

For a complete template, see this post.

// List posts alphabetically under first letter of title
$args = array(
  'orderby' => 'title',
  'order' => 'ASC',
  'caller_get_posts' => 1,
  'posts_per_page' => 20,
 );
query_posts($args);
if (have_posts()) {
   $curr_letter = '';
   while (have_posts()) {
      the_post();
      $this_letter = strtoupper(substr($post->post_title,0,1));
      if ($this_letter != $curr_letter) {
         echo "<h2> # $this_letter #</h2>";
         $curr_letter = $this_letter;
      }
      ?>
      <br />
      <a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>"><?php the_title(); ?></a>
   <?php }
}

8 Responses to List Posts Alphabetically Under First Letter Of Title

  • Jamil Ahmed says:

    Awesome…. I am trying to get AZ index of posts from current category page in archive.php and did not solve until I found code from genius here. This is so simple and I have customized it for my template. Thanks Mac You saved me today

  • As Mac said, the mb_ family of functions is essential for languages such as Greek and good handling in general of the utf-8 characters. I tested straight on a live site and it works beautifully! thank for the code.

  • derek says:

    I am trying to wrap the output into divs for example I want to be able to group the letter A in a div with all of the posts that start with the letter A. This way you could have more control of styling the output. Does that make sense?

    • Mac says:

      I have not tested this, but it should be close. Make the changes shown below and also add a closing div tag just after the closing brace for the while loop:

         $curr_letter = '';
         $letter_div = '<div class="letter-wrap">';
         echo $letter_div;
         while (have_posts()) {
            the_post();
            $this_letter = strtoupper(substr($post->post_title,0,1));
            if ($this_letter != $curr_letter) {
               if ($curr_letter !== '') echo "<p class='letter-back'><a href='#letter-index' >Back to Index</a></p></div>$letter_div";
               echo "<a name='letter-$this_letter'></a><br />";
               echo "<h2> # $this_letter #</h2>";
               $curr_letter = $this_letter;
            }
            ?>
      
  • Nick Melistas says:

    is it possible to add am a to z index above the listing? so when the user clicks on a letter then scroll down to the the specified articles starting with the clicked letter.

    • Mac says:

      Please excuse the crude coding. I think this should get you started:

      if (have_posts()) {
         echo '<a name="letter-index"></a><br />';
         echo '<h2>Index</h2>';
         echo '<p class="letter-index">';
         $curr_letter = '';
         foreach ( $wp_query->posts as $post ) {
            $this_letter = strtoupper(substr($post->post_title,0,1));
            if( $this_letter != $curr_letter ) {
               echo "<a class='letter-link' href='#letter-$this_letter' > [ $this_letter ] </a>";
               $curr_letter = $this_letter;
            }
         }
         echo '</p>';
         rewind_posts();
         $curr_letter = '';
         while (have_posts()) {
            the_post();
            $this_letter = strtoupper(substr($post->post_title,0,1));
            if ($this_letter != $curr_letter) {
               if ($curr_letter !== '') echo "<p class='letter-back'><a href='#letter-index' >Back to Index</a></p>";
               echo "<a name='letter-$this_letter'></a><br />";
               echo "<h2> # $this_letter #</h2>";
               $curr_letter = $this_letter;
            }
            ?>
            <br />
            <a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>"><?php the_title(); ?></a>
      
  • HyperGuy says:

    Was trying to find a way to query posts by first letter.

    But for certain alphabets like y, z, etc.. even if there exists no posts beginning by those letters. I get the result that they exist.

    I am not sure whether its due to the the SQl Query I am using as it is posted above.

    Any suggestions would be very helpful.

    • Mac says:

      If you are using multi-byte characters (for example, Arabic), try changing this:

      $this_letter = strtoupper(substr($post->post_title,0,1));
      

      to this:

      $this_letter = mb_strtoupper(mb_substr(apply_filters('the_title',$post->post_title),0,1));
      $this_letter = mb_convert_encoding($letter,'UTF-8', mb_detect_encoding($this_letter) );
      

      If you want the letters to appear in the original encoding, try leaving out the second line above.

Leave a Reply

Your email address will not be published. Required fields are marked *

*