I have a CPT and I am changing its ordering by a numeric value of a custom field. My custom field name is "ordering". The ordering of my CPT is changed like this:
$posts = get_posts(array(
'posts_per_page' => -1,
'post_type' => 'staff',
'meta_key' => 'ordering',
'orderby' => 'meta_value',
'order' => 'ASC'
));
The ordering of CPT items is working fine but when I click a CPT item, I see the pagination is still follwoing the "Created Date" ordering format. Is there a way to match the pagination ordering the same way the CPT items are ordered?
I am using understrap_post_nav()
to output my pagination.
I tried to change the ordering of my pagination with these arguments but this didn't work:
understrap_post_nav($args = array(
'orderby' => 'meta_value',
'meta_key' => 'ordering',
'order' => 'ASC',
'post_type' => 'staff',
'posts_per_page' => -1,
));
I believe understrap_post_nav()
code is coming from here:
.php
and this is the while loop:
.php
Here's how I am getting the posts and I am getting these post in my custom page template called about-page.php
:
<?php
while ( have_posts() ) {
the_post();
get_template_part( 'loop-templates/content', 'page' );
}
?>
<div class="container" id="team-members-loop">
<?php
$posts = get_posts(array(
'posts_per_page' => -1,
'post_type' => 'team-members',
'meta_key' => 'ordering',
'orderby' => 'meta_value',
'order' => 'ASC'
));
if( $posts ): ?>
<div class="row">
<?php foreach( $posts as $post ):
setup_postdata( $post );
?>
<div class="col-sm-4">
<a href="<?php the_permalink(); ?>" class="team-link">
<div class="card_image_container">
<div class="card_image" style="background-image:url(<?php the_field('thumbnail_photo') ?>)"></div>
</div>
<div class="card_details">
<h4 class="card-title"><?php the_title(); ?></h4>
<h5 class="card-desc"><?php echo the_field('title') ?></h5>
</div>
</a>
</div>
<?php endforeach; ?>
</div>
<?php wp_reset_postdata(); ?>
<?php endif; ?>
</div>
I have a CPT and I am changing its ordering by a numeric value of a custom field. My custom field name is "ordering". The ordering of my CPT is changed like this:
$posts = get_posts(array(
'posts_per_page' => -1,
'post_type' => 'staff',
'meta_key' => 'ordering',
'orderby' => 'meta_value',
'order' => 'ASC'
));
The ordering of CPT items is working fine but when I click a CPT item, I see the pagination is still follwoing the "Created Date" ordering format. Is there a way to match the pagination ordering the same way the CPT items are ordered?
I am using understrap_post_nav()
to output my pagination.
I tried to change the ordering of my pagination with these arguments but this didn't work:
understrap_post_nav($args = array(
'orderby' => 'meta_value',
'meta_key' => 'ordering',
'order' => 'ASC',
'post_type' => 'staff',
'posts_per_page' => -1,
));
I believe understrap_post_nav()
code is coming from here:
https://github.com/understrap/understrap/blob/main/inc/template-tags.php
and this is the while loop:
https://github.com/understrap/understrap/blob/main/single.php
Here's how I am getting the posts and I am getting these post in my custom page template called about-page.php
:
<?php
while ( have_posts() ) {
the_post();
get_template_part( 'loop-templates/content', 'page' );
}
?>
<div class="container" id="team-members-loop">
<?php
$posts = get_posts(array(
'posts_per_page' => -1,
'post_type' => 'team-members',
'meta_key' => 'ordering',
'orderby' => 'meta_value',
'order' => 'ASC'
));
if( $posts ): ?>
<div class="row">
<?php foreach( $posts as $post ):
setup_postdata( $post );
?>
<div class="col-sm-4">
<a href="<?php the_permalink(); ?>" class="team-link">
<div class="card_image_container">
<div class="card_image" style="background-image:url(<?php the_field('thumbnail_photo') ?>)"></div>
</div>
<div class="card_details">
<h4 class="card-title"><?php the_title(); ?></h4>
<h5 class="card-desc"><?php echo the_field('title') ?></h5>
</div>
</a>
</div>
<?php endforeach; ?>
</div>
<?php wp_reset_postdata(); ?>
<?php endif; ?>
</div>
Share
Improve this question
edited Feb 16, 2022 at 22:21
hnnnng
asked Feb 14, 2022 at 22:49
hnnnnghnnnng
1191 silver badge7 bronze badges
7
|
Show 2 more comments
1 Answer
Reset to default 1Is there a way to match the pagination ordering the same way the CPT items are ordered?
The custom pagination function that you're using (understrap_post_nav()
) is using the default functions for navigating between singular posts like previous_post_link()
and next_post_link()
which do not support custom (posts) queries, so custom coding is needed to achieve the pagination you're trying to have.
And one easy way I could think of is by using offset like so:
In your loop in the
about-page.php
template, add a custom URL parameter to the post permalink.Just use any name that you like, but in my example (see the code at the bottom of this answer), the parameter name is
current_ordering
.That parameter will store the offset of the current post in the
$posts
array, which contains all posts since you're using'posts_per_page' => -1
which retrieves all found posts. I.e. There'd be noLIMIT
clause added to the query/SQL.Then in the single post template like
single.php
, make the same query in question, but query for 3 posts only starting from the post at the offset of the previous post, i.e.current_ordering - 1
.And basically, the pagination will be generated based on the above 3 posts, and the pagination links will also need to have the
current_ordering
parameter which is passed to the next/previous post.
So here's a working example and just follow the steps:
In the
about-page.php
, change theforeach( $posts as $post )
toforeach( $posts as $i => $post )
, i.e. add the post index/offset ($i
).Then change the
<?php the_permalink(); ?>
to<?php my_ordering_permalink( $i ); ?>
.In your
functions.php
file, add this which defines the above function that outputs the permalink containing thecurrent_ordering
parameter:/** * Display or retrieve the current post permalink with a current_ordering parameter added. * * @param int $offset Required. The post's position/offset in the posts array. * @param WP_Post|int $post Optional. The post object or ID. Default null for current post. * @param bool $echo Optional. Whether to echo or return the URL. Default true. * * @return void|string Void if `$echo` argument is true, the permalink URL `$echo` is false. */ function my_ordering_permalink( $offset, $post = null, $echo = true ) { $url = add_query_arg( 'current_ordering', $offset, get_permalink( $post ) ); if ( ! $echo ) { return $url; } echo $url; }
Also in the functions file, add this which outputs the pagination: (you can customize the HTML markup later on)
/** * Displays a (simple) pagination to navigate between singular posts in a custom posts query. * * @uses understrap_post_nav() * * @param string $sep Optional. String to use between the next/previous links. Default ' '. * @param string $before Optional. String to use before the pagination. Default empty. * @param string $after Optional. String to use after the pagination. Default empty. */ function my_ordering_post_nav( $sep = ' ', $before = '', $after = '' ) { // Use understrap_post_nav() if the URL parameter isn't set, or if we're not on a // single team-members CPT post page. if ( ! isset( $_GET['current_ordering'] ) || ! is_singular( 'team-members' ) ) { return understrap_post_nav(); } $current = get_queried_object_id(); $offset = $_GET['current_ordering']; $ids = get_posts( array( 'fields' => 'ids', 'offset' => max( 0, $offset - 1 ), 'posts_per_page' => 3, // the rest below should be the same as the one used with get_posts() in the // about-page.php template 'post_type' => 'team-members', 'meta_key' => 'ordering', 'orderby' => 'meta_value_num', 'order' => 'ASC', ) ); if ( empty( $ids ) ) { return; } $current_index = array_search( $current, $ids ); if ( false === $current_index ) { return; } $prev_index = $current_index + 1; $next_index = $current_index - 1; $links = array(); if ( isset( $ids[ $prev_index ] ) ) { $post_id = $ids[ $prev_index ]; $links[] = sprintf( '<a href="%s">« %s</a>', esc_url( my_ordering_permalink( $offset + 1, $post_id, false ) ), esc_html( get_the_title( $post_id ) ) ); } if ( isset( $ids[ $next_index ] ) ) { $post_id = $ids[ $next_index ]; $links[] = sprintf( '<a href="%s">%s »</a>', esc_url( my_ordering_permalink( $offset - 1, $post_id, false ) ), esc_html( get_the_title( $post_id ) ) ); } echo $before . implode( $sep, $links ) . $after; }
Then in your single post template, change the
understrap_post_nav();
tomy_ordering_post_nav();
.
So that's all, but keep in mind that the query arguments in the my_ordering_post_nav()
function must match the ones in the about-page.php
template (the args you pass to get_posts()
), except for fields
, offset
and posts_per_page
.
Additional Notes
'posts_per_page' => -1
is equivalent to'nopaging' => true
, which can result in a huge query that can cause the site to run extremely slow if not completely down, depending on whether the database can handle the posts selection (which in your case selecting by a meta value), so useposts_per_page
with a high number instead that you know would never actually going to be reached, but that can be handled by the database and that would also not cause timeouts (which can happen when looping over a large array or dataset)."I am changing its ordering by a numeric value of a custom field" — if the meta value is a number, then you should use
'orderby' => 'meta_value_num'
to make sure the values are sorted as numbers and not strings. That way,1, 3, 10, 2
would correctly be sorted into1, 2, 3, 10
and not1, 10, 2, 3
which is what would happen when the values are sorted as strings.get_posts()
suppresses all filters by default, so I suggest you to add'suppress_filters' => false
to your args to ensure plugins can filter the query or run specific actions (for a good reason, of course).You might want to create a single post template specific to your CPT, i.e.
single-team-members.php
, and edit that file to use themy_ordering_post_nav()
function, which means you would not need to edit thesingle.php
file.In
about-page.php
, instead of simplyif( $posts )
, you should useif( ! empty( $posts ) )
to check or ensure that the$posts
/array is not empty.
understrap_post_nav()
to output my pagination." - what's the code inunderstrap_post_nav()
, and how you do your loop (what's your "foreach $posts" code)? – Sally CJ Commented Feb 15, 2022 at 4:52$posts = get_posts(...)
call, which I didn't see in thesingle.php
file? So basically, please include all relevant code. – Sally CJ Commented Feb 16, 2022 at 1:09