0

I'm trying to make a page on my WordPress website to display all kinds of food through 26 loops.

Every loop has to loop a letter of the alphabet, and on top of the page I have links that will link to the anchor boxes around the loops.

So what I want to be displayed is something like this:

NAV:

a b c d e ...(and so on) ... z

A

All items starting with the letter A

B

All items starting with the letter B

And so on..


After reading this topic: Display all posts starting with given letter? I decided to use diffrent terms for the letters.

For this I made a custom post type called 'waaier' In there I have a custom taxonomy called 'waaier_abc' And in there diffrent terms for each letter called 'waaier_a' , 'waaier_b' and so on

I think the most logical way to mage 26 loops beneath each other, because I want each letter in a diffrent div as well.

I tried this loop for it but it doesn't display anything, also not the else statement..

<div class="waaier_a_object">
                    <?php query_posts(array('post_type' => 'waaier', 'waaier_abc' => $term->waaier_a ) ); ?>
                    <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
                    <?php endwhile; else: ?>
                    <p><?php _e('Sorry, de letter a bevat nog geen inhoud.'); ?></p>
                    <?php endif; ?>
                </div>

Does anyone have an idea for an other loop too display terms from a certain post type OR to displaying posts with a certain first letter of a certain post type.

Sorry if my english is looking weird

1 Answer 1

2

What I can say on your code:

  • 26 loops are really a lot for a page, that page will load very slowly, unless you setup some cache
  • Please, do not use query_posts it is very poor performant when called once, 26 times is performance hell
  • If you set the taxonomy only to show this page, you do not need that that taxonomy at all

What I suggest:

Perform only one query using WP_Query instance

$args = array(
   'post_type' => 'waaier',
   'posts_per_page' => -1
);
$query = new WP_Query($args);

This query will return all the posts of waaier type.

After that you can start the loop saving all posts in a helper array to order them by letter just taking first letter fo the post:

$by_letter = array();
while( $query->have_posts() ) { $query->the_post();
  global $post;
  $letter = substr($post->post_name, 0, 1);
  if ( ! isset($by_letter[$letter]) ) $by_letter[$letter] = array();
  $by_letter[$letter][] = $post;
}
wp_reset_postdata();

After this loop, you will have the array $by_letter filled with the posts orderd by letters, so you can loop this array to show posts:

if ( ! empty( $by_letter ) ) {

  ksort($by_letter); // order the array

  // fill the array with letters have no posts
  $by_letter = fill_by_letter_array( $by_letter );

  display_letters_anchors( array_keys( $by_letter ) );

  foreach( $by_letter as $letter => $posts ) {
  ?>
    <div id="waaier_<?php echo $letter; ?>" class="waaier_<?php echo $letter; ?>_object">
    <?php
    if ( ! empty($posts) ) {
      foreach ( $posts as $post ) {
        setup_postdata($post);
        // just an example of post output
        echo '<p><a href="' . get_permalink() . '">' . get_the_title() . '</a></p>';
      }
    } else {
       echo '<p>' . __('Sorry, de letter a bevat nog geen inhoud.') . '</p>';
    }
    ?>
    </div>
  <?php
  }
  wp_reset_postdata();
}

In this code I've used the 2 functions display_letters_anchors and fill_by_letter_array, first to show the links to every letter div, second to fill the array for letters that have no posts.

That functions (can be putted in functions.php) should be something like:

function display_letters_anchors( $letters ) {
   if ( empty($letters) ) return;
   echo '<ul class="waaier_letters_list">';
   foreach ( $letters as $letter ) {
     echo '<li><a href="#waaier_' . $letter . '">';
     echo strtoupper($letter) . '</a></li>';
   }
   echo '</ul>';
}

function fill_by_letter_array( $by_letter ) {
  $keys = range('a', 'z');
  $values = array_fill(0, count($keys), array());
  $empty = array_combine($keys, $values);
  return wp_parse_args( $by_letter, $empty);
}

This is more performant: only one query instead of 26, and you do not need to setup the right taxonomy for the post letter, everything is done automatically.

2
  • I understand the looping a bit I think I don't need the functions part because I did alreadyhardcode my navigation. So I removed it and also removed the line that calls the function. When I still had it it displayed a '0' under my navigation and above my posts, and all my posts were wrapped in div#waaier_0 , but I don't have posts starting with 0, Also it's not really alphabetic, C comes first, than a, s, and the alphabet backwards. I don't know why..your code seems really logical. Also, is it possible to still display the div of a letter even if it is empty?
    – Maartje
    Oct 17, 2013 at 10:17
  • 2
    @Maartje I've edited the code and fix some errors, now it should works. After that, why hardcoding navigation when you can create it autmatically? If you want to chenge something you have to edit one line, not 26...
    – gmazzap
    Oct 17, 2013 at 10:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.