I want to sort the result of a WP_query()
alphabetically by nickname (optional custom field) if present, last name (in post title) if not.
Sorting order:
Sample data:
Post 1
Title: 'John Adams'
Nickname: ''
Post 2
Title: 'Joe Car'
Nickname: ''
Post 3
Title: 'John Earnest'
Nickname: ''
Post 4
Title: 'James Water'
Nickname: 'Bumblebee'
Post 5
Title: 'John Zebra'
Nickname: 'Disco'
Desired output:
An object/array similar in structure to a result of WP_query()
(that I can check have_posts
against); that has posts in this order
The post_title
is a person's first and last name.
There is an optional custom field for the person's nickname, custom_field_nickname
.
I want to return all the superhero
-type posts (that either have a nickname or do not). Current query:
$args = array( 'post_type' => 'superhero' );
$query = new WP_Query( $args );
Currently my function that sort these posts using add_filter
:
function posts_orderby_lastname ($orderby_statement)
{
$orderby_statement = "RIGHT(post_title, LOCATE(' ', REVERSE(post_title)) - 1) ASC";
return $orderby_statement;
}
How can I modify that filter or somehow set the orderby
option for my desired post order?
Use below code to address your requirement:
<?php
query_posts(array('post_type' => 'superhero'));
$names = array();
?>
<?php if ( have_posts() ) : ?>
<?php while (have_posts()) : the_post(); ?>
<div id="lists">
<ul>
<?php
// check whether custom field exist or not
if (get_post_meta($post->ID, 'nick_name', true) ) { // custom field exist
$explode = explode(' ',get_the_title()); // explode main title
$nick = get_post_meta($post->ID, 'nick_name', true); // get nickname
$names[] = $explode[0].' '.$nick.' '.$explode[1]; // form a name with Firstname Nickname LastName
} else { // no custom field value
$explode = explode(' ',get_the_title()); // explode main title
$names[] = $explode[0].' '.$explode[1]; // Form a name with Firstname Lastname
}
?>
</ul>
</div>
<?php endwhile; ?>
<?php endif; ?>
<?php wp_reset_query();?>
<?php
/* Sort function to sort array */
function cmp($a, $b)
{
$a = substr(strstr($a," "), 1);
$b = substr(strstr($b," "), 1);
return strcasecmp($a, $b);
}
uasort($names, "cmp");
foreach ($names as $key => $value) {
echo $value.'<br />';
}
?>
So I ended up doing this:
// Build post queries
$query = new WP_Query($args);
// Extract post array from objects
$queryPosts = $query->posts;
// Custom sort each array according to "nickname"
usort($queryPosts, compare_the_posts);
// Replace old array of posts with newly sorted one
$query->posts = $queryPosts;
Combined with this custom compare function
// If a post has a specified "nickname", use that to sort with. If not, use the last word of the post title (last name)
function compare_posts($a, $b) {
if (strlen($a->nick_name) > 0) {
$a = $a->nick_name;
} else {
$a = last_word($a->post_title);
}
if (strlen($b->nick_name) > 0) {
$b = $b->nick_name;
} else {
$b = last_word($b->post_title);
}
return strcasecmp($a, $b);
}
// (Helper function) Last word of a sentence
function last_word($str) {
$last_word_pos = strrpos($str, ' ') + 1;
$last_word = substr($str, $last_word_pos);
return $last_word;
}
Hope this will help you.
REQUEST:SELECT SQL_CALC_FOUND_ROWS wp_posts.ID
FROM wp_posts
INNER JOIN wp_postmeta
ON (wp_posts.ID = wp_postmeta.post_id)
INNER JOIN wp_postmeta AS mt1
ON (wp_posts.ID = mt1.post_id)
WHERE 1=1
AND wp_posts.post_type = 'post'
AND (wp_posts.post_status = 'publish')
AND (wp_postmeta.meta_key = 'about_order'
AND mt1.meta_key = 'job_title' )
GROUP BY wp_posts.ID
ORDER BY wp_postmeta.meta_value DESC
LIMIT 0, 12
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.