I’m working on a custom post type archive and I want to add an A-Z filtering menu. I managed to pretty much get it working following this thread (Create alphabetical Pagination in wordpress) but I dont understand how my initial page (/exposants) can show all the results.
<div class="exposant__filter" id="exposants"> <a href="/exposants/#exposants"><?php _e('Tout', 'festival'); ?></a> <?php $posts = get_posts(array( 'numberposts' => -1, 'post_type' => 'exposant', 'orderby' => 'title', 'order' => 'ASC', )); $firstLetters = array(); foreach($posts as $post) { $title = $post->post_title; $startingLetter = substr($title, 0, 1); $dupeFirstLetters[] = $startingLetter; $firstLetters = array_unique($dupeFirstLetters); sort($firstLetters); } foreach($firstLetters as $letter) { echo "<a href="?lettre=$letter">$letter</a>"; } if(!empty($_GET['lettre'])) { $letter = $_GET['lettre']; } else { $letter = $firstLetters[0]; } ?> </div> <?php $exposantsArchive = new WP_Query(array( 'posts_per_page' => -1, 'post_type' => 'exposant', 'orderby' => 'title', 'order' => 'ASC', )); ?> <div class="row row--2col u-m-top--8"> <?php while($exposantsArchive->have_posts()) { $exposantsArchive->the_post(); $first_letter = strtoupper(substr(apply_filters('the_title',$post->post_title),0,1)); $logo = get_field('logo'); if($first_letter == strtoupper($letter)) { ?> <div class="exposant__thumb col--padding-right"> <div class="exposant__logo"> <img src="<?php echo $logo['url'] ?>" alt="<?php echo $logo['alt'] ?>"> </div> <div class="exposant__thumb-content"> <h2 class="heading--as-h4 heading--no-margin"><?php the_title(); ?></h2> <?php $related = get_field('pieces_liees'); if($related) { echo '<p class="exposant__categories">'; foreach ($related as $k=>$category) { if($k) echo '/'; ?> <a href="<?php echo get_the_permalink($category); ?>"><?php echo get_the_title($category); ?></a> <?php } } ?></p> <p class="exposant-thumb__excerpt"><?php echo wp_trim_words( get_field('description'), 16, '...' ); ?></p> <a href="<?php the_permalink(); ?>" class="btn"><?php _e('Plus de détails', 'festival'); ?></a> </div> </div> <?php } } wp_reset_postdata() ?> </div>
I imagine I’d have to replace the else {$letter = $firstLetters[0];} but I have no idea with what.
Thanks in advance for your precious support.
EDIT!
Here is the solution that ended up working flawlessly!
So in functions.php
<?php add_filter( 'posts_where', 'tomtom_posts_where', 10, 2 ); function tomtom_posts_where( $args, $wp_query_obj ) { global $wpdb; $starts_with = $wp_query_obj->get( 'starts_with' ); if ( $starts_with ) { $args .= ' AND ' . $wpdb->posts . '.post_title LIKE '' . esc_sql( $wpdb->esc_like( $starts_with ) ) . '%''; } return $args; }
And here is the page
<?php /** * Outputs an alphabetic paginator. * * @return void */ function tomtom_output_alphabetic_paginator() { $posts = get_posts( array( 'numberposts' => -1, 'post_type' => 'exposant', 'orderby' => 'title', 'order' => 'ASC', ) ); $firstLetters = array(); foreach ( $posts as $post ) { $title = $post->post_title; $startingLetter = substr( $title, 0, 1 ); $dupeFirstLetters[] = $startingLetter; } $firstLetters = array_unique( $dupeFirstLetters ); sort( $firstLetters ); echo "<a href="/exposants/#exposants">" . __('Tout', 'festival') . "</a>"; foreach ( $firstLetters as $letter ) { echo "<a href="?lettre={$letter}#exposants">{$letter}</a>"; } } /** * Gets an array of exposant custom post types. * * @return array */ function tomtom_get_exposants() { $args = array( 'posts_per_page' => -1, 'post_type' => 'exposant', 'orderby' => 'title', 'order' => 'ASC', ); if ( !empty( $_GET['lettre'] ) ) { $args['starts_with'] = $_GET['lettre']; } $wp_query = new WP_Query( $args ); return $wp_query->get_posts(); } /** * Outputs links related to exposant custom post type object. * * @return void */ function tomtom_output_related( $related ) { foreach ( $related as $k => $category ) { if ( $k ) { echo ' / '; } echo "<a href="" . get_the_permalink( $category ) . "">" . get_the_title( $category ) . "</a>"; } } ?> <div class="exposant__filter" id="exposants"> <?php tomtom_output_alphabetic_paginator(); ?> </div> <?php $exposantsArchive = tomtom_get_exposants(); ?> <div class="row row--2col u-m-top--8"> <?php foreach ( $exposantsArchive as $exposant ): ?> <?php $logo = get_field('logo', $exposant->ID); ?> <?php $related = get_field('pieces_liees', $exposant->ID); ?> <?php $description = get_field('description', $exposant->ID); ?> <div class="exposant__thumb col--padding-right"> <div class="exposant__logo"> <img src="<?php echo $logo['url'] ?>" alt="<?php echo $logo['alt'] ?>"> </div> <div class="exposant__thumb-content"> <h2 class="heading--as-h4 heading--no-margin"><?php echo $exposant->post_title; ?></h2> <?php if ( $related ): ?> <p class="exposant__categories"> <?php tomtom_output_related( $related ); ?> </p> <?php endif; ?> <p class="exposant-thumb__excerpt"><?php echo wp_trim_words( $description, 20, '...' ); ?></p> <a href="<?php get_permalink( $exposant->ID ); ?>" class="btn"><?php _e( 'Plus de détails', 'festival' ); ?></a> </div> </div> <?php endforeach; ?> </div>
Advertisement
Answer
If I understand the problem correctly, here’s an slightly optimized version of your code. I’ve taken the liberty of decoupling your php and your html as much as I could for clarity.
It’s not tested, it may take a few tweaks, but overall I hope this does the trick!
In your functions.php file, add this, which will allow you to filter your database queries by first letter:
add_filter( 'posts_where', 'tomtom_posts_where', 10, 2 ); function tomtom_posts_where( $args, $wp_query_obj ) { global $wpdb; $starts_with = $wp_query->get( 'starts_with' ) if ( $starts_with ) { $args .= ' AND ' . $wpdb->posts . '.post_title LIKE '' . esc_sql( $wpdb->esc_like( $starts_with ) ) . '%''; } return $where; }
Then:
<?php /** * Outputs an alphabetic paginator. * * @return void */ function tomtom_output_alphabetic_paginator() { $posts = get_posts( array( 'numberposts' => -1, 'post_type' => 'exposant', 'orderby' => 'title', 'order' => 'ASC', ) ); $firstLetters = array(); foreach ( $posts as $post ) { $title = $post->post_title; $startingLetter = substr( $title, 0, 1 ); $dupeFirstLetters[] = $startingLetter; } $firstLetters = array_unique( $dupeFirstLetters ); sort( $firstLetters ); echo "<a href="/exposants/#exposants">" . __('Tout', 'festival') . "</a>"; foreach ( $firstLetters as $letter ) { echo "<a href="?lettre={$letter}">{$letter}</a>"; } } /** * Gets an array of exposant custom post types. * * @return array */ function tomtom_get_exposants() { $args = array( 'posts_per_page' => -1, 'post_type' => 'exposant', 'orderby' => 'title', 'order' => 'ASC', ); if ( ! empty( $_GET['lettre'] ) ) { $args['starts_with'] = $_GET['lettre']; } return new WP_Query( $args ); } /** * Adds fields to an exposant custom post type object. * * @param WP_Post $exposant Exposant custom post type. * @return void */ function tomtom_hydrate_exposant( &$exposant ) { $exposant->logo = get_field( 'logo', $exposant->ID ); $exposant->related = get_field( 'pieces_liees', $exposant->ID ); $exposant->description = get_field( 'description', $exposant->ID ); } /** * Outputs links related to exposant custom post type object. * * @return void */ function tomtom_output_related( $exposant ) { if ( ! isset( $exposant->related ) ) { tomtom_hydrate_exposant( $exposant ); } foreach ( $exposant->related as $k => $category ) { if ( $k ) { echo '/'; } echo "<a href="" . get_the_permalink( $category ) . "">" . get_the_title( $category ) . "</a>"; } } ?> <div class="exposant__filter" id="exposants"> <?php tomtom_output_alphabetic_paginator(); ?> </div> <?php $exposantsArchive = tomtom_get_exposants(); ?> <div class="row row--2col u-m-top--8"> <?php foreach ( $exposantsArchive as $exposant ): ?> <?php tomtom_hydrate_exposant( $exposant ); ?> <div class="exposant__thumb col--padding-right"> <div class="exposant__logo"> <img src="<?php echo $exposant->logo['url'] ?>" alt="<?php echo $exposant->logo['alt'] ?>"> </div> <div class="exposant__thumb-content"> <h2 class="heading--as-h4 heading--no-margin"><?php echo $exposant->post_title; ?></h2> <?php if ( $exposant->related ): ?> <p class="exposant__categories"> <?php tomtom_output_related( $exposant->related ); ?> </p> <?php endif; ?> <p class="exposant-thumb__excerpt"><?php echo wp_trim_words( $exposant->description, 16, '...' ); ?></p> <a href="<?php get_permalink( $exposant->ID ); ?>" class="btn"><?php _e( 'Plus de détails', 'festival' ); ?></a> </div> </div> <?php endforeach; ?> </div>