skip to Main Content

I would like to create a glossary overview page on wordpress via PHP, which can be used via a shortcode. I would like that always the initial letter is displayed and then the individual topics (posts) which begin with this.

Example:

A

  • Apple
  • Apricot

B

  • Banana
  • Blackberry

and so on…

To implement this I use the following code:

  // get glossary

function glossary($post_id) {

$all_posts = new WP_Query(
    array(
 'posts_per_page'    => -1,
    'post_type'         => 'glossar',
        'orderby' => 'title',
        'order' => 'ASC',
));

    
        
    
echo '<ul>';
if( $all_posts->have_posts()){
     
 foreach( range( 'A', 'Z' ) as $letter ) {
     
echo '<div class="group_letter"><div class="letter">' . $letter. '</div>';  
        while( $all_posts->have_posts() ){
            $all_posts->the_post();
            $title = get_the_title(); 
            $name = get_post_field( 'post_name', get_post() );
            $initial = strtoupper( substr( $title, 0, 1 ) );                        
            
                
            
            if( $initial == $letter ){
                
                echo '<li><a class="glossary-listing" href="/glossar/'. $name . '">' . $title . '</a></li>';
                
            }
            
        }
        $all_posts->rewind_posts();
     
    }
} 
echo '</ul>';

}
add_shortcode( 'glossary', 'glossary' );

So far it works, but now it shows letters for which there are no posts. This is how it looks now

I have tried to do it with an if query, but so far, I am stuck. Can someone help me?
Best regards and thank you!

2

Answers


  1. I am sure there is a better solution besides running 26 times through the while loop. Anyway, here is what you are looking for.

    // get glossary
    function glossary($post_id) {
        $all_posts = new WP_Query(
            [
                'posts_per_page' => -1,
                'post_type'      => 'glossar',
                'orderby'        => 'title',
                'order'          => 'ASC',
            ]
        );
    
        echo '<ul>';
    
        if ($all_posts->have_posts()) {
            foreach (range('A', 'Z') as $letter) {
                $foundPostable = false;
                while ($all_posts->have_posts()) {
                    $all_posts->the_post();
                    $title = get_the_title();
                    $name = get_post_field( 'post_name', get_post() );
                    $initial = strtoupper(substr($title, 0, 1));
    
                    if ($initial === $letter) {
                        if ($foundPostable === false) {
                            $foundPostable = true;
                            echo '<div class="group_letter"><div class="letter">' . $letter. '</div>';
                        }
                        echo '<li><a class="glossary-listing" href="/glossar/'. $name . '">' . $title . '</a></li>';
                    }
                }
                $all_posts->rewind_posts();
            }
        }
        echo '</ul>';
    }
    add_shortcode( 'glossary', 'glossary' );
    

    As for improvement, something like this might work as well.

    // get glossary
    function glossary($post_id) {
        $all_posts = new WP_Query(
            [
                'posts_per_page' => -1,
                'post_type'      => 'glossar',
                'orderby'        => 'title',
                'order'          => 'ASC',
            ]
        );
    
        echo '<ul>';
    
        $startLetter = '';
        while ($all_posts->have_posts()) {
            $all_posts->the_post();
            $title = get_the_title();
            $name = get_post_field( 'post_name', get_post() );
            $initial = strtoupper(substr($title, 0, 1));
    
            if ($initial !== $startLetter) {
                $startLetter = $initial
                echo '<div class="group_letter"><div class="letter">' . $letter . '</div>';
            }
    
            echo '<li><a class="glossary-listing" href="/glossar/'. $name . '">' . $title . '</a></li>';
        }
    
        echo '</ul>';
    }
    add_shortcode('glossary', 'glossary');
    
    Login or Signup to reply.
  2. Sort the array using PHP sort() function then loop through the result

    <?PHP
    $list=['apples','popsicles','Zinger','donkeys','bananas','joe',
    'Locusts','gazelles','Angels','Popsicle','Dongle','jump','cocoa'
    ];
    //convert all elements to same case
    //sorting will sort by case
    $list =array_map('strtolower', $list);
    //sort the array
    sort($list);
    $last_letter=null;
    foreach($list as $item){
    $current_letter=substr($item,0,1);
    if($last_letter!=$current_letter){
    ?>
        <div style="margin:1rem;padding:1rem;background:#f5f5f5;">
            <?=$current_letter?>
        </div>
    <?php
    
        $last_letter=$current_letter;
    
    }
    ?>
    <div style="margin:1rem;padding:1rem;background:#f5f5f5;">
    <?=$item?>
    </div>
    <?PHP
    
    }
    ?>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search