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>
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>